[英]How do you explain the output from this function-like macro `slice` in C?
#include <stdio.h>
#define slice(bare_string,start_index) #bare_string+start_index
#define arcane_slice(bare_string,start_index) "ARCANE" #bare_string+start_index
int main(){
printf("slice(FIRSTA,0)==> `%s`\n",slice(FIRSTA,0));
printf("slice(SECOND,2)==> `%s`\n",slice(SECOND,2));
printf("slice(THIRDA,5)==> `%s`\n",slice(THIRDA,5));
printf("slice(FOURTH,6)==> `%s`\n",slice(FOURTH,6));
printf("slice(FIFTHA,7)==> `%s`\n",slice(FIFTHA,7));
printf("arcane_slice(FIRSTA,0)==> `%s`\n",arcane_slice(FIRST,0));
printf("arcane_slice(SECOND,2)==> `%s`\n",arcane_slice(SECOND,2));
printf("arcane_slice(THIRDA,5)==> `%s`\n",arcane_slice(THIRDA,5));
printf("arcane_slice(FOURTH,6)==> `%s`\n",arcane_slice(FOURTH,6));
printf("arcane_slice(FIFTHA,7)==> `%s`\n",arcane_slice(FIFTHA,7));
return 0;
}
OUTPUT: OUTPUT:
slice(FIRSTA,0)==> `FIRSTA`
slice(SECOND,2)==> `COND`
slice(THIRDA,5)==> `A`
slice(FOURTH,6)==> ``
slice(FIFTHA,7)==> `slice(FIFTHA,7)==> `%s`
`
arcane_slice(FIRSTA,0)==> `ARCANEFIRST`
arcane_slice(SECOND,2)==> `CANESECOND`
arcane_slice(THIRDA,5)==> `ETHIRDA`
arcane_slice(FOURTH,6)==> `FOURTH`
arcane_slice(FIFTHA,7)==> `IFTHA`
I have the above C code that I need help on. 我有上面的C代码,需要帮助。 I am getting weird behaviour from 我从中得到奇怪的行为
the function-like macro slice
that is supposed to 'slice' from a passed index 应该从传递的索引中“切片”的类似函数的宏slice
to the end of the string. 到字符串的末尾。 It does not slice in the real sense but passes 它不是真正意义上的切片而是通过
a pointer from a certain point to printf
which starts printing from that 从某个点到printf
的指针,该指针从该点开始打印
address. 地址。 I have managed to figure out that in arcane_slice
the strings 我设法找出在arcane_slice
的字符串
are concatenated first then 'sliced'. 先级联然后“切片”。 I also have figured out that when start_index
我也想通了,当start_index
is equal to 6 printf
starts printing from the null byte and that is why 等于6 printf
从空字节开始打印,这就是为什么
you get the 'empty' string. 您将获得“空”字符串。 The strange part is when start_index
is 7. It prints 奇怪的是start_index
为7时显示
the first argument to printf
(interpolator string) concatendated with the passed bare string in both. printf
的第一个参数(内插器字符串)与两者中传递的裸露字符串相结合。
arcane_slice
and slice
(as shown in the 5th and 10th lines in the output) arcane_slice
和slice
(如输出中的第5行和第10行所示)
Why is that so? 为什么会这样?
My wildest guess is that when the start_index
exceeds the length of the strings, 我最疯狂的猜测是,当start_index
超过字符串的长度时,
the pointer points to the start of the data segment in the program's address space. 指针指向程序地址空间中数据段的开头。 But 但
then you could counter that with "why didn't it start printing from FIRSTA
" 那么您可以使用“为什么它不从FIRSTA
开始打印”来进行FIRSTA
Not any "data segment", the stack. 没有任何“数据段”,堆栈。 This is what I remember: when C calls a function it first puts data on stack, first variable arguments, then the format, all being the addresses to the memory sequentially allocated with your text. 这就是我所记得的:当C调用一个函数时,它首先将数据放在堆栈上,第一个变量参数,然后是格式,所有这些都是随文本顺序分配的内存地址。 In that block of memory, the last argument (c-string) goes first, and the first goes last, thus: 在该内存块中,最后一个参数(c字符串)位于第一个,最后一个位于最后一个,因此:
Memory: 记忆:
"FIFTHA\0slice(FIFTHA,7)==> `%s`\n\0"
Arguments: 参数:
<pointer-to-"FIFTHA"> <pointer-to-"slice...">
Since you overincrement the first one it skips the '\\0'
character and points at the format as well. 由于您过度增加了第一个字符,因此它会跳过'\\0'
字符并指向格式。
Try to experiment with this with more placeholders, like 尝试使用更多占位符对此进行试验,例如
printf("1: %s, 2: %s\n", slice(FIFTHA,7), slice(FIFTHA,6));
slice(bare_string,start_index) #bare_string+start_index
you are passing a string
and bare_string
stores the starting address of string which you have passed and then you returning changed pointer location which is bare_string+start_index
您正在传递一个string
而bare_string
存储已传递的string
的起始地址,然后返回更改的指针位置,即bare_string+start_index
char str[6]="Hello";
char *ptr =str;
printf("%s\n",str);//prints hello
printf("%s\n",str+1);//prints ello
printf("%s\n",str+2);//prints llo
printf("%s\n",str+3);//prints lo
printf("%s\n",str+4);//prints o
printf("%s %c=%d \n",str+5,*(str+5),*(str+5));//prints Null
printf("%s %c=%d \n",str+6,*(str+6),*(str+6));//prints Null or may be Undefined behavior
printf("%s %c=%d \n",str+7,*(str+7),*(str+7));//prints Null or may be Undefined behaviour
the same scenario is happing in your case. 您的情况也存在相同的情况。
Test Code: 测试代码:
#include<stdio.h>
main()
{
char str[6]="Hello";
char *ptr =str;
printf("%s\n",str);//prints hello
printf("%s\n",str+1);//prints ello
printf("%s\n",str+2);//prints llo
printf("%s\n",str+3);//prints lo
printf("%s\n",str+4);//prints o
printf("%s %c=%d \n",str+5,*(str+5),*(str+5));//prints Null
printf("%s %c=%d \n",str+6,*(str+6),*(str+6));//prints Null or may be Undefined behavior
printf("%s %c=%d \n",str+7,*(str+7),*(str+7));//prints Null or may be Undefined behaviour
}
You have answered your question yourself. 您已经回答了自己的问题。 "FIFTHA"+7
gives you a pointer outside the string object, which is undefined behavior in C. "FIFTHA"+7
为您提供了字符串对象外部的指针,这在C语言中是未定义的行为。
There's no easy way to get a more Python-like behavior for such "slices" in C. You could make it work for indexes up to a certain upper limit by adding a suffix to your string, full of zero bytes: 对于C中的此类“切片”,没有简单的方法来获得更像Python的行为。通过在字符串中添加一个后缀(零字节为零),可以使其在索引达到一定上限时起作用:
#define slice(bare_string,start_index) ((#bare_string "\0\0\0\0\0\0\0")+(start_index))
Also, when using macros, it's good practice (and avoids bugs too) to use parentheses excessively. 另外,使用宏时,过度使用括号是一种很好的做法(并且也避免了错误)。
#define slice(bare_string,start_index) ((#bare_string)+(start_index))
#define arcane_slice(bare_string,start_index) (("ARCANE" #bare_string)+(start_index))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.