【问题标题】:Char * array confusionchar * 数组混淆
【发布时间】:2017-09-20 10:07:34
【问题描述】:
#include <stdio.h>

const int MAX = 4

int main () {

    char *names[] = {
      "Zara Ali",
      "Hina Ali",
      "Nuha Ali",
      "Sara Ali"
    };

    int i = 0;

    for ( i = 0; i < MAX; i++) {
        printf("Value of names[%d] = %s\n", i, names[i] );
    }

    return 0;
}

为什么可以只打印names[i] 而不是*names[i]?有人可以提供一个内存图来澄清吗?

【问题讨论】:

标签: c arrays string char


【解决方案1】:

char 是单个 8 位字符,我们在 c 中通过使用第一个字符的地址来表示长度未知的 char 数组来表示字符串,因此对于单个字符串,我们使用

char * name

意思是name包含了第一个字符的内存地址(指针),我们可以通过增加内存地址name+1得到第二个字符。 如果我们想要一个字符串数组,我们实际上要做的是拥有指向多个字符串的内存地址(指针)数组,所以

char * names[] = ...

是一个指向字符串第一个字符的指针数组,您必须指定 c 数组中的元素数,但由于您已经为其提供了值,编译器可以为您推断元素数。

names 中每个元素指向的每个字符串都可以位于内存中的任何位置,它只是一个内存地址数组,names[0] 可以等于10000 和 names[1] 可能等于 10,这意味着字符串 0 从地址 10000 开始,字符串 1 从地址 10 开始,但是由于您声明它的方式,编译器很可能会将它们放入内存顺序一个接一个,但您可以稍后为任何一个值分配不同的内存地址。

names[2] = "New Values";

names[2] 的值将是内存中存在“新值”的不同位置,原始字符串“Nuha Ali”仍将位于内存中它的原始位置未受影响。

如果你愿意,你可以像这样创建一个 char 数组

char     names[] = "Zara Ali\0Hina Ali\0...

然后 names 将被创建足够长以包含整个字符串,并且字符串将被复制到数组中,而不是每个字符串的第一个字符内存地址被复制到数组中。 names 将只指向单个字符数组,而 names[1] 将返回第二个字符,您将无法确定字符串的结束位置,任何 str 函数都将假定字符串以第一个 '\0' 结束。

(注意:您的编译器可能不允许您实际在字符串中间放置一个字符串终止符 '\0',我没有尝试过,虽然我认为如果不是这样应该是合法的,但您知道如何内存可以布局)。

【讨论】:

  • 没有假设字符串以第一个 \0 结尾; 定义 (C11 §7.7.7/1) 确实如此。此外,"Zara Ali\0Hina Ali\0" 不是字符串,而是字符串文字。字符串文字不必是字符串 (C11 §6.4.5)。不过,嵌入的 \0 字符是合法的。
  • printf("%s\n", "abc\0def" ) 输出 abc 和 strcmp("abc\0def", "abc") == 0。
【解决方案2】:

我认为不需要内存图。

c 中带 * 的任何内容都是内存中的指针。

所以,

int *a = 3;

a = 3;
*a = memory address

printf("result = %d, result 2 =%d\n", a, *a);

输出:

result = 3, result 2 = 9023923 (this is a random memory address)

你必须记住这个!

【讨论】:

  • 我了解这对 int 是如何工作的,但我只是对 char* 数组感到困惑。
【解决方案3】:

这是因为* 包含在[] 中。 看看Array subscripting

下标运算符[]的定义是E1[E2]等同于(*((E1)+(E2)))

【讨论】:

    【解决方案4】:

    格式说明符%s 需要(char*) 类型的参数,即指向字符数组的指针。

    char* names[] 中,每个元素都是这样一个指向字符数组的指针;在初始化之后,names[0] 拥有一个指向字符串文字 "Zara Ali" 开头的内存地址。因此,将这样的指针作为参数传递给printf("%s", ...) 是正确的。

    然而,如果你写*names[0],那么你实际上取消引用这个指针,产生一个char-值,在这种情况下是'Z'。这就像您编写了 printf("%s", 'Z'),这样预期的数据类型 char* 和实际的数据类型 char 不匹配并产生编译器警告,并且 - 忽略它们时 - 未定义的行为。

    【讨论】:

      猜你喜欢
      • 2011-11-08
      • 2021-11-18
      • 1970-01-01
      • 2020-03-04
      • 1970-01-01
      • 1970-01-01
      • 2015-08-26
      • 2013-06-04
      • 2015-07-16
      相关资源
      最近更新 更多