2

这周我一直在努力熟悉 C。我一直在阅读C Primer Plus(第 5 版),但我仍然在变量和指针方面遇到了一些问题。

这是我用来测试的脚本:

int main (int argc, char **argv) {


    char *myvariable=NULL;


    myvariable = strdup("apples");
    myvariable = strdup("value updated");

    printf("========== \n\n");
    printf("this is the thing   : %p \n", myvariable);
    printf("this is the thingval: %s \n", myvariable);


    setvariable(&myvariable);


    printf("after function - this is the thing   : %p \n", myvariable);
    printf("after function - this is the thingval: %s \n", myvariable);


    return 0;

}


int setvariable(char **myvariable) {

    *myvariable = strdup("value from function");
    return 1;

}

运行它的输出给了我:

this is the thing   : 0x7fee9b4039c0 
this is the thingval: value updated 
after function - this is the thing   : 0x7fee9b4039d0 
after function - this is the thingval: value from function 

问题

这是否char *myvariable=NULL;意味着这myvariable是一个指针或一个变量?这个答案表格char *ptr = "string";只是向后兼容const char *ptr = "string";

  1. 真的吗?
  2. 我在创造一个不变的角色吗?
  3. 那些不应该是不可变的吗?如果是这样,为什么我可以更新值?

使用函数setvariable(char **myvariable)- 是**myvariable“指向指针的指针”吗?

或者myvariable实际上只是一个字符串(以 nul 结尾的字符数组)?

这是我找到的一些代码(没有文档),所以我有很多关于它的问题。下一个是为什么以myvariable这种方式定义 - 像以下方式之一那样设置它会不会更好:

char myvariable[] = "apples";
char myvariable[6] = "apples";

我也不明白为什么当setvariable被调用时它似乎是在传递 myvariable 的地址&- 传递一个指针不是更好吗?

在询问之前,我曾尝试对此进行研究 - 但两天后进展缓慢,我想要一些建议。

澄清询问

我问的原因是因为从我读过的内容来看,如果某些东西*后面有一个,char *myvariable那么它应该是一个指针。

但是,我无法创建一个char不是指针的指针并分配myvariable指针指向它。

4

5 回答 5

2

char *myvariable=NULL; 意味着 myvariable 是指针还是函数?

myvariable是一个指针(即一个变量,因为指针一个变量)。

1)这是真的吗?

我认为这不是真正的向后兼容性。但是,诸如字符串之类的字符串"string" 表现为常量字符串。

2)我是在创造一个不变的角色吗?

试图修改字符串的字符"string"是一种未定义的行为。没有const,因为匿名字符串的类型是char[]。但程序员经常建议将其声明为const,以防止错误。

3)那些不应该是不可变的吗?如果是这样,为什么我可以更新值?

您无法修改*myvariable(只要将其分配给字符串 litteral),但您可以修改指针myvariable

使用函数 setvariable(char **myvariable) - **myvariable 是“指向指针的指针”吗?

是的。

或者 myvariable 实际上只是一个字符串(以 nul 结尾的字符数组)?

*myvariable是一个字符串一个指向char.

顺便说一句,我想你应该阅读这个答案

于 2013-06-07T18:48:41.420 回答
1

char *myvariable=NULL; 意味着 myvariable 是指针还是变量?

myvariable是“指针char”类型的变量。它将用于存储“char”类型对象的地址。

这个答案说 The form char *ptr = "string"; 只是向后兼容 const char *ptr = "string";

从什么向后兼容?

字符串文字表达式"string"的类型为“7 元素数组char”(6 个字符加上 0 个终止符)。在 C 中,“N-element array of ”类型的表达式T将转换为“pointer to T”类型的表达式,其值将是数组中第一个元素的地址,除非数组表达式是sizeofor 一元运算&符,或者是用于在声明中初始化另一个数组的字符串文字。

所以当你写

char *ptr = "string";

该表达式"string"不是asizeof或一元运算符的操作数&,也不是用于在声明中初始化数组,因此它的类型从“7元素数组char”转换为“指针char”,并且指针值(地址数组的第一个元素)被复制到ptr.

C 的一个问题是尝试修改字符串文字的内容会调用未定义的行为。有些平台将字符串文字放在只读内存中,有些则没有;如果代码中存在多个实例,有些会创建文字的多个实例,有些只在文字上创建一个实例。因此,尝试修改文字可能在某些平台上起作用,在其他平台上导致访问冲突,在其他平台上导致不可预知的行为等。C 语言标准明确地未定义行为,因此实现可以自由地以任何方式处理这种情况觉得合适。

作为一项安全措施,大多数人明确声明指针为const char *

const char *ptr = "string";

这样你就不能通过ptr. 请注意,C++ 的不同之处在于字符串文字的类型为“array of ”,因此这些表达式无论如何 const char都会被转换为。const char *

我问的原因是因为从我读过的内容来看,如果某些东西后面有 *,比如 char *myvariable,那么它应该是一个指针。

在 C(和 C++)中,声明基于表达式的类型;声明中的表达式形式与代码中的表达式形式相匹配。

例如,如果我们有一个名为指向 a 的指针变量pint并且我们想要访问该整数值,我们使用一元运算符取消引用该指针*

x = *p;

表达式 的类型*pint,所以变量 p的声明是

int *p;

变量的类型p是“指针int”。的int-nessp由类型说明符给出int;的指针性p声明 *p者给出。请注意,*绑定到标识符,而不是类型说明符;即使您可以将声明写为

int* p;

它被解释为

int (*p);
于 2013-06-09T12:08:34.460 回答
0
char c;  // allocates a variable with space to hold one character
char *p; // allocates a pointer that may point to a character

p = &c;  // sets variable p to point to the storage allocated for c

c = 'a';   // stores character 'a' in the storage allocated for c
*p = 'a';  // has exact same result as previous


char const *mesg = "abcd";
// allocates 5 characters ('a', 'b', 'c', 'd', '\0')
// also allocates a pointer that may point to a character
// also makes the pointer point to the literal string "abc"

char buf5[] = "abcd";
// Allocates 5 characters ('a', 'b', 'c', 'd', '\0')...
// the compiler figures out how many values need to go in the array.
// Variable buf5 is a reference to this array
char x5[] = { 'a', 'b', 'c', 'd', '\0' };
// has exact same result as previous

sizeof(buf5)  // evaluates to the value 5

int i5[5];
sizeof(i5)  // evaluates to: sizeof(int) * 5
sizeof(buf5)  // evaluates to: sizeof(char) * 5
// but sizeof(char) is always 1 (by definition!)


sizeof(p) // evaluates to size of a pointer (probably 4 or 8)
// size of pointer does not change no matter which string it points to

buf5[0] = 'A'; // now s3 holds: "Abcd"
*buf5 = 'A'; // has exact same result as previous

buf5[1] = 'B'; // now s3 holds: "ABcd"
*(buf5 + 1) = 'B'; // has exact same result as previous

您可以轻松地覆盖 char 数组中的字符,buf5但不能增加为其分配的存储大小;您只能重复使用现有存储。

当您声明一个数组时,您“拥有”存储空间;C 为您设置。当您使用文字字符串时,您可能会或可能无法摆脱对它的写入,最好不要尝试。文字可能被放置在特殊的地方(例如嵌入式系统的 ROM 中),甚至可能无法写入,因此任何依赖于写入文字的程序都是不必要的不​​可移植。

至于注...

在 C 语言中,当您使用指针时,如果您*在其前面放置 a,则您取消引用该指针。这使您可以检查指针指向的内容或修改它。

当您声明一个指针时,在 C 中您使用相同的语法声明它,这有点棘手。但这里有一些例子:

char c;  // c has the type char
char *p;  // when you dereference the pointer p, you get type char
// Assume p contains garbage right now; we have no idea where it might point

c = 'a'; // legal: assigning a char value to a char type
*p = 'a'; // legal just as above

p = &c;  // p now points to the storage for variable c

char **pp; // pp is a pointer to a pointer to char
// If you dereference pp twice you get a char
// If you dereference pp once you get a char *, a pointer to char
// Assume pp contains garbage right now; we have no idea where it might point

pp = &p;  // pp now points to the storage of p (which is a pointer pointing to c)

*p = 'a'; // dereference p to find the char to assign (variable c)
*(*pp) = 'a';  // dereference pp to find p, dereference p in turn to find char to assign
**pp = 'a';  // parentheses not required, same as previous line

在 C 中,函数总是按值调用:函数的参数被复制。因此,要从函数内部修改某些内容,您需要传递一个指针;指针被复制,但随后指针的值用于查找要修改的变量。

令人困惑的是,您的示例函数想要修改指针。因此,您声明它需要 a char **,并在调用函数时获取指针的地址。

于 2013-06-07T20:09:10.340 回答
0

通过编写char *myvariable, int foo, double blah, or void (*funcptr)(void),你声明了一个具有某种类型的变量。变量的类型指定存储在该变量中的内容:指针、数字或结构。

因此,char *myvariable是一个包含指针值的变量(一些保留的内存量)。

于 2013-06-07T18:47:40.947 回答
0

char* myvariable-char*正在设置一个指向保存类型对象的内存位置的指针char

myvariable是用于引用该位置的变量。

要获得价值,您必须使用取消引用&myvariable

我在 10 多年前做过 C++,而不是 C,但我认为那是相当准确的。

于 2013-06-07T18:49:53.333 回答