【问题标题】:What is difference between char name[11]; and char *name;char name[11]; 之间有什么区别?和字符*名称;
【发布时间】:2015-03-12 02:29:45
【问题描述】:

下面是查找指向数组的指针的简单代码。

#include <stdio.h>
typedef unsigned short int Ushort;

void InputYear(char (*name), Ushort *year);

int main(int argc, const char * argv[]) {
    Ushort year;
    char name[11] ;    

    InputYear(name, &year);

    printf("MY name is %s", message);
    printf("%d", year);
}

void InputYear(char (*name), Ushort *year){
    printf("please enter your name and year");
    scanf("%s %hd" ,name, year);
}

但问题是,如果我更改char name[11] --> char *name 为什么它不起作用?

错误是“分段错误:11”。

我了解到数组的名称也是一个指针,表示第一个数组值的地址。在这方面,我认为char name[11]char *name 是一样的。

或者有什么我不知道的吗?

和额外的问题:

int a = 1;
int* b = &a;
printf("%s", *b);

它有效。关键是 printf 的第二个参数是值本身,而不是地址。但是,

char hi[11] = "message";
printf("%s", hi);

在这种情况下, printf 的第二个参数是地址本身,而不是上面的值。它是什么??为什么会这样?

非常感谢!

【问题讨论】:

  • printf("%s", *b); 起作用的事实是一个有争议的问题,因为它是未定义的行为。至于第一个问题,char name[11] 自动为 11 个chars 分配空间,而char *name 只是声明了一个指针——它实际上并没有指向任何东西。
  • printf("%s", *b) 不“工作”,也许你的意思是%d
  • 尝试阅读C FAQ章节

标签: c arrays pointers


【解决方案1】:

为什么如果我更改 "char name[11]" --> "char *name" 不起作用?

name 是在堆栈上定义的指针,并使用垃圾地址初始化,因此它指向一个随机位置,并且取决于它指向的位置,您可能会或可能不会遇到分段错误。即使您没有遇到分段错误,代码仍然会被视为有缺陷。

编辑:

指向数组的指针和仅指针有什么区别?

您可能是指数组和指针之间的差异。如果是这样的话,数组的名字是一个常量指针,一个指针是一个非常量指针。

【讨论】:

    【解决方案2】:

    因为

    char name[11];
    

    表示创建一个11字符数组,而

    char *name;
    

    意思是,创建一个指针,稍后用它指向某个地方,然后你就可以这样做了

    name = malloc(11);
    

    这将指向11 字符的内存块。

    当您调用 scanf 时,它期望参数指向有效内存以写入其中。

    所以如果指针没有初始化,你不知道它指向哪里,malloc 让你访问内存并返回一个指向它的指针,你将该指针分配给name 然后name变得可写,但还不可读。

    它指向的内容还没有定义,所以你也需要初始化它的内容,你可以使用它

    scanf("%10s", name);
    

    注意"%10s" 这样可以防止写入超出允许的内存,它对malloc 和数组都有用。

    注意scanf("%10s", name);中的数字应该是数组可以容纳-1的字符数,因为你需要一个额外的字符,终止符'\0'

    在对malloc 的任何调用之后,您应该承担两个责任,首先您必须确保有有效的内存指向,在相反的情况下malloc 将返回一个特殊值NULL,因此正确调用malloc 将是

    name = malloc(11);
    if (name == NULL)
        handleThisAndDontTryToUse_name_Anywhere();
    

    第二件事,系统将获得指针指向的内存的所有权,直到您决定可以释放它,为此您需要调用free()

    /* after you are done using the block of memory */
    free(name);
    

    如果是

    char name[11];
    

    您不必担心这些事情。

    您可以做的第三件事是创建数组并使用char *name; 我的意思是指向它

    char array[11];
    char *name = array;
    

    现在name 是指向array 第一个元素的指针,从您的问题文本中,我相信您明白这意味着什么。

    【讨论】:

    • char buff[11]; char *name = buff; 是这个答案中唯一缺少的东西。
    • 当然,数据在内存中的实际存储位置也存在巨大差异,您完全忽略了这一点。 char array[11] 将在堆栈中,而 char *name; name = malloc(sizeof(char)*20); 将来自堆。
    【解决方案3】:
    char name[11];
    

    分配 11 个字节的可写内存,您可以在其中存储输入。 name 被视为指向该内存的常量指针。

    char *name;
    

    为名为@9​​87654324@ 的指针变量分配空间,该变量可以更改,但不指向任何内容。

    char *name = "Fred";
    

    为字符串“Fred”分配指针变量和 5 个字节,但在不可写内存中。

    【讨论】:

    • 在第一种情况下,name 是一个数组,而不是任何类型的指针(常量或其他)
    • 数组名称在幕后和运行时与常量指针完全相同。在编译期间,它们在符号表中有不同的类型,但它们编译成完全相同的东西。我想这对迂腐的语言律师类型会有所不同,但如果你真正理解 C 在做什么——不仅在编译器级别,而且在实际运行的代码中——差异是没有意义的。
    • 差异在各个层面都至关重要。您可能会发现char name[11]; 保留(至少)11 字节的堆栈空间,但char *const name = (whatever); 保留4(加上任何“任何”保留);这些金额是不同的。此外,类型区别在运行时仍然存在,例如int x; scanf("%d\n, &amp;x); char name[x]; printf("%d\n", sizeof name);。如果name 在某个阶段归结为一个常量指针,那么sizeof name 会给你一个指针的大小,但它没有。类型系统在 C 中至关重要,它不仅仅是一个烦人的细节。
    • 是的,是的,我当然明白配置和其他编译时的区别。您在“解释”的许多细节上都犯​​了错误。首先, const 指针不分配内存,它是一个常量。其次,sizeof 是一个编译时操作符,所以它当然是不同的。这就是我要说的:如果你以 char a[11]; char * const b = a; 之类的东西开始一个 C 文件,那么文件中后面的任何代码——任何表达式、任何函数(除了像 sizeof 这样的编译时东西)——都会逐位生成a 和 b 的代码相同。
    • sizeof 不是编译时运算符(在我之前评论的代码示例中,它的结果取决于一个直到运行时才知道的值)。在您的最新句子中,&amp;b 的行为与 &amp;a 不同。您是否知道有时被描述为“衰减”的转换规则,以及“右值”的含义?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-04
    • 2011-01-28
    • 2018-11-05
    相关资源
    最近更新 更多