C++ 指向字符串和字符catch 22的指针

C++ 指向字符串和字符catch 22的指针,c++,c,pointers,C++,C,Pointers,我正在研究指针,当我看到char*p[10]时,我被卡住了。因为有些事情被误解了。有人能一步一步地解释为什么我的逻辑是错误的,错误是什么,我在哪里错了,我应该怎么想。因为我想准确地学习。还有int*p[10]此外,例如x是指向char的指针,但只是char而不是char。但是为什么char*x=“可能” 我认为上面的一个应该是正确的,但是,我已经看到了char*name[]={“no month”,“jan”,“feb”} char ),或者指向一个数组中的第一个项( char []/COD>

我正在研究指针,当我看到
char*p[10]
时,我被卡住了。因为有些事情被误解了。有人能一步一步地解释为什么我的逻辑是错误的,错误是什么,我在哪里错了,我应该怎么想。因为我想准确地学习。还有
int*p[10]此外,例如x是指向char的指针,但只是char而不是char。但是为什么
char*x=“可能”

我认为上面的一个应该是正确的,但是,我已经看到了
char*name[]={“no month”,“jan”,“feb”}
两者都是正确的

C或C++中的指针可以指向单个项(单个代码> char <代码>),或者指向一个数组中的第一个项(<代码> char []/COD>)。


因此a
char*p[10]定义可以指向10个单个字符或10个数组(即10个字符串)。

您的
char*p[10]
图表显示了一个数组,其中每个元素指向一个字符。
您可以这样构造它:

char f = 'f';
char i = 'i';
char l1 = 'l';
char l2 = 'l';
char a1 = 'a';
char r1 = 'r';
char r2 = 'r';
char a2 = 'a';
char y = 'y';
char nul = '\0';
char *p[10] = { &f, &i, &l1, &l2, &a1, &r1, &r2, &a2, &y, &nul };
这与阵列非常不同

char p[10] = {'f', 'i', 'l', 'l', 'a', 'r', 'r', 'a', 'y', '\0'};

它们是字符数组,而不是指针

指针同样可以很好地指向数组的第一个元素,正如您可能在类似的构造中看到的那样

const char *p = "fillarray";
其中
p
保存由文本定义的数组的第一个元素的地址

这是因为数组可以衰减为指向其第一个元素的指针

如果创建指针数组,也会发生同样的情况:

/* Each element is a pointer to the first element of the corresponding string in the initialiser. */
const char *name[] = { "no month","jan","feb" };
你会得到同样的结果

const char* name[3];
name[0] = "no month";
name[1] = "jan";
name[2] = "feb";

让我们回到基础上来

首先,char*p只是一个指针。p只包含一个内存地址。这个内存地址可以指向任何东西,任何地方。按照惯例,我们总是使用NULL(或者,我讨厌这种方法,将其赋值为零——是的,它们是同一个“东西”,但NULL传统上与指针一起使用,所以当您的眼睛掠过代码时,您会看到NULL——您认为是“指针”)

无论如何,指向的内存地址可以包含任何内容。因此,要在语言中使用,我们键入它,在本例中,它是指向字符(char*p)的指针。这可以通过类型转换来覆盖,但这要等到以后

第二,每当我们看到p[10],我们都知道我们正在处理一个数组。同样,数组可以是字符数组、整数数组等,但它仍然是一个数组

您的示例:char*p[10]不过是一个由10个字符指针组成的数组。不多不少。你的问题出现是因为你试图把“字符串”的概念强加于此。C中没有字符串。C中没有对象。可以肯定地使用以NULL结尾的字符串的概念。但C中的“字符串”不过是一个字符数组,以NULL结尾(或者,如果使用某些适当的函数,可以使用特定数量的字符–strncpy而不是strcpy,等等)。但是,从外观上看,C语言中没有字符串,它们只不过是字符数组,有一些支持函数在遇到NULL时会停止遍历数组

所以–char a[10]–只是一个长度为10个字符的字符数组。你可以用你想要的任何字符来填充它。如果其中一个是空字符,那么它将终止通常称为“C样式字符串”的内容。有些函数支持这种类型的字符数组(即“字符串”),但它仍然使用字符数组

<>你的困惑是因为你试图混合C++字符串对象,并强迫这个概念到C字符数组。正如ugoren所指出的,您的示例都是正确的,因为您处理的是字符指针数组,而不是字符串。同样,在该字符数组中的某个位置放置NULL得到了几个C函数的支持,这些函数使您能够使用“类似字符串”的概念,但它们不是真正的字符串。当然,除非你想表达一个字符串只不过是一个字符跟在另一个字符后面——一个数组

char c = 'a';
这里,
c
是一个字符,通常是编码数据的单个字节

char* ptr = &c;
ptr
是一个
char
指针。在C语言中,它所做的只是指向一个内存位置,并不保证该位置上有什么。您可以使用
char*
将char传递给函数,以允许函数允许函数更改该
char
(按引用传递)

一种常见的C约定是
char*
指向一个内存位置,其中几个字符按顺序存储,后跟空字符
\0
。此约定称为C字符串:

 char const* cstr = "hello";
cstr
指向一个6字节长的内存块,以空字符结尾。数据本身无法修改,但指针可以更改为指向其他对象

char
s的数组看起来相似,但行为略有不同

 char arr[] = "hello";
这里的
arr
是一个由6个
char
s组成的内存块。由于
arr
表示内存本身,因此无法将其更改为指向其他位置。但是数据可以修改

现在,

是指向字符的指针数组。
name
是一个内存块,每个内存块包含指向以null结尾的字符串的指针

在图中,我认为是意外地使用了
string*
而不是
char*
。左侧和右侧之间的差异实际上不是技术上的差异,而是使用
char*
的方式上的差异。在左侧,每个
char*
指向一个字符,而在右侧,每个
char*
指向一个以空结尾的字符块。

注意
 char arr[] = "hello";
char const* name[] = { "Jan", " Feb"..., "Dec"};