Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 韩元';t在给定的用户定义函数中,计算顺序无法将源字符串复制到目标字符串?_C_String_Pointers_Operator Keyword_Operator Precedence - Fatal编程技术网

C 韩元';t在给定的用户定义函数中,计算顺序无法将源字符串复制到目标字符串?

C 韩元';t在给定的用户定义函数中,计算顺序无法将源字符串复制到目标字符串?,c,string,pointers,operator-keyword,operator-precedence,C,String,Pointers,Operator Keyword,Operator Precedence,上面的代码块是一个用户定义的函数,用于将一个字符串的内容复制到另一个字符串的末尾。 在这里,我们遍历目标字符串,直到它碰到空字符'\0'。第二个while循环用于将源字符串中的内容复制到目标字符串的末尾 我已经读到,*ptr++之类的表达式根据C中的运算符优先级表计算为*(ptr++)。 如果是这种情况,表达式:*dest++=*src++不应该计算为 *(dest++)=*(src++)? 这会不会导致dest首先指向内存中的下一个位置并更新其值,而不是使用源字符串中的字符更新'\0'?类似地

上面的代码块是一个用户定义的函数,用于将一个字符串的内容复制到另一个字符串的末尾。
在这里,我们遍历目标字符串,直到它碰到空字符
'\0'
。第二个while循环用于将源字符串中的内容复制到目标字符串的末尾

我已经读到,
*ptr++
之类的表达式根据C中的运算符优先级表计算为
*(ptr++)

如果是这种情况,表达式:
*dest++=*src++
不应该计算为
*(dest++)=*(src++)

这会不会导致dest首先指向内存中的下一个位置并更新其值,而不是使用源字符串中的字符更新
'\0'
?类似地,它不会导致
src
遗漏源字符串的第一个字符吗


但是,该函数似乎成功地将源字符串的内容复制到目标字符串的末尾。

使用后缀
++
运算符,在当前上下文中对操作数求值后,操作数将递增。在此表达式中,
dest
的当前值被取消引用并分配给位置,
src
的当前值被取消引用并分配给左侧

根据本规范第6.5.2.4节:

2后缀
++
运算符的结果是操作数的值。
作为副作用,操作数对象的值 增加(即,添加适当类型的值1) )。请参阅加法运算符和 有关约束、类型和类型的信息的复合赋值 转换和操作对指针的影响最新版本 结果的值计算顺序在边之前 使用更新操作数存储值的效果。 对于不确定顺序的函数调用 后缀
++
的操作是一个单独的计算。后缀
++
在 原子类型的对象是具有
内存顺序
内存顺序语义

因此:

void mystrcat(char* dest,char* src)
{
    while(*dest) dest++;
    while(*dest++=*src++);
    return;
}
与(大致)相同:

*dest++=*src++

您缺少的是
*dest++
使用post-increment。这意味着表达式
dest++
返回递增之前的值,这就是我们用
*
取消引用的指针。因此,它分配给内存中的当前位置,然后递增指针

*dest=*src;
dest+=1;
src+=1;
实际上相当于:

*dest++ = *src++;
如果您改为写下以下内容,则会出现您描述的问题:

*dest = *src;
dest++;
src++;
因为pre-increment使变量递增,并计算为新值,即下一个位置


请参见

重要的是要注意,后缀增量或减量表达式在应用相应运算符之前计算为表达式的值。递增或递减操作在计算操作数后发生。请参阅:在执行第一个while循环之后,您已经到达了一个NUL字节,因此不应该递增
dest
NULL
是一个带有空指针常量的宏,而不是一个字符。您指的是ASCII
NUL
或空字符或
'\0'
0
@Olaf我指的是空字符'\0'。对不起,这句话模棱两可。它不是模棱两可的,只是错了。记住这一点@瑞安·麦库拉:没错!这就是重点。此函数不应工作。@TirthaSarathiGhosh因为后增量具有更高的优先级,它相当于
*(dest++)
。如果取消引用具有更高的优先级,则相当于
(*dest)+
对不起,我使用括号是错误的。求值应该是*(dest++)而不是(*dest++),因为后增量具有更高的优先级。@TirthaSarathiGhosh,这正是它的本质。这就是你在问题中写的。请重读问题的最后几点。我明确指出,计算*(dest++)而不是(*dest++)将导致dest首先指向内存中的下一个位置,并更新其值,而不是使用源字符串中的字符更新“\0”。我在回答中解释了为什么这不是真的
dest++
首先计算,但其值是
dest
的旧值。然后我们用
*
解除对旧值的引用,因此我们更新当前位置,而不是下一个位置。
*(++dest) = *(++src);