首页 > 解决方案 > 指针的原因是在第二种情况下指向字符串文字的最后一个字符

问题描述

情况1:

# include<stdio.h>
int main() {
    int l=0;
    char *names[4] = {
        "Arijit",
        "Rohit",
        "Debojyoti",
        "Abhisek"
    };
    while(l<4)
    {
        printf("Address %u contains %s\n",names[l],names[l]);/*here instead of of names[l] for strings when I used names[l++] the memory order changed look at the output*/ 
        l++;
    }
    return 0;
}

输出 1:

Address 4210688 contains Arijit
Address 4210695 contains Rohit
Address 4210701 contains Debojyoti
Address 4210711 contains Abhisek

输出 2:

Address 4210695 contains Arijit
Address 4210701 contains Rohit
Address 4210711 contains Debojyoti
Address 45 contains Abhisek

查看第二个 o/p Debojyoti 包含 10 个字符,包括 '\0' 所以 Rohit 被分配地址 4217011。为什么?再看看 Abhisek 被分配到一个与其他三个名字不连续的内存位置。为什么?

标签: cpointersmemory-address

解决方案


问题是 C没有定义函数参数的评估顺序。时期。在大多数情况下,C 没有定义二元运算符的操作数求值顺序。

因此,在同一个表达式中同时使用和修改变量通常是错误的。(对于语言律师:不,我不是指编译器会检测到的错误!未定义的行为情况是合法的 C,但代码仍然是错误的。)

您的第二版声明,缩短,看起来像:

    printf("%p, %s, %s\n", names[l], names[l], names[l++]);

C 可以自由地以printf()任何顺序评估这些参数。这意味着l==0在语句开始时,第一次迭代的以下任何解释都是可能的:

    printf("%p, %s, %s\n", names[0], names[0], names[0]); l+=1;
    printf("%p, %s, %s\n", names[0], names[1], names[0]); l+=1;
    printf("%p, %s, %s\n", names[1], names[0], names[0]); l+=1;
    printf("%p, %s, %s\n", names[1], names[1], names[0]); l+=1;

在同一个编译器上,您可以看到调试和优化编译之间出现不同的顺序。中间两种解释不太可能,但在符合标准的编译器中仍然允许。只有第 4 个参数保证评估为names[0]', due to the definition of postfix++`。

正如我上面所说,避免在同一个表达式中使用和修改同一个变量。在不能保证操作顺序的情况下严格避免它,即使在只有一种解释可能的极少数情况下也要三思而后行。Guido Van Rossum(Python 语言的发明者)指出,程序的阅读频率高于编写频率。让团队中的其他程序员感到困惑——甚至是你自己在一两年内回来编辑代码时,都会产生一定的成本。

当“经过测试的”生产代码在编译器升级后开始失败时,成本会更高。


推荐阅读