首页 > 解决方案 > `char *` 和 `int *` 之间的不同语义

问题描述

我想知道为什么在 C 中声明和分配 achar *与 anint *具有不同的语义。

以下所有代码都是clang使用 flags 编译的-Wall -Werror -std=gnu99 --pedantic。我试图了解差异是否只是存在,或者之间是否存在更大的差异int *char *我还没有意识到。

// this will compile
int main(int argc, const char *argv[]) {
    char *a;
    a = "1";

    printf("a: %s\n", a);
    return EXIT_SUCCESS;
}
// this will not compile. It's a parallel construction, substituting char for int
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[]) {
    int *a;
    a = 1;

    printf("a: %d\n", a);
    return EXIT_SUCCESS;
}
// but this will compile
#include <stdio.h>
#include <stdlib.h>

int main(int argc, const char *argv[]) {
    int *a;
    int b = 1;
    a = &b;

    printf("a: %d\n", *a);
    return EXIT_SUCCESS;
}

标签: cpointers

解决方案


您正在处理数组、指针和标量语义之间的差异。

除非它是sizeof或一元运算符的操作数&,或者是用于在声明中初始化字符数组的字符串字面量,否则“N 元素数组”类型的表达式T将被转换(“衰减”)为键入“pointer to T”,表达式的值将是数组第一个元素的地址。

字符串字面"1"量是类型为 的数组表达式char [2]。在这种情况下,它“衰减”为 类型的表达式,表达式char *的值是字符串第一个字符的地址。所以你分配喜欢喜欢:

 a = "l"; // char * = char *

整数变体不会发生这种情况。文字1有 type int,但您试图将该int值分配给一个int *对象:

a = 1; // int * = int 

这应该触发诊断。您只能int *int *对象赋值 - 您需要显式转换1

a = (int *) 1; 

这将抑制诊断,但1很可能不是您平台上的有效内存地址,尝试使用它会导致问题。


推荐阅读