用“char *”定义的变量是c中的指针或char类型的变量吗?

时间:2013-06-07 18:41:20

标签: c

本周我一直在努力学习C语言。我一直在阅读C Primer Plus (5th Edition) ,但我对变量和指针仍然有点麻烦。

这是我用来测试的脚本:

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是指针或变量? This answer表单char *ptr = "string";只是向后兼容const char *ptr = "string";

  1. 这是真的吗?
  2. 我是否创造了一个恒定的角色?
  3. 那些应该是不可变的吗?如果是,为什么我可以更新值?
  4. 使用函数setvariable(char **myvariable) - **myvariable是“指向指针的指针”吗?

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

    这是我发现的一些代码(没有文档)所以我对它有很多疑问。下一个问题是为什么myvariable以这种方式定义 - 并且将它设置为以下方式之一并不是更好:

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

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

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

    要求澄清

    我问的原因是因为形式我读过它看起来像是*后面有char *myvariable,如char那么它应该是一个指针。

    但是,我在创建不是指针的myvariable时遇到问题,并指定{{1}}指针指向它。

5 个答案:

答案 0 :(得分: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的指针。

顺便说一句,我想你应该阅读this answer

答案 1 :(得分:1)

  

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

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

  

这个答案说形式char * ptr =“string”;只是const char * ptr =“string”;

的向后兼容性

的向后兼容性?

字符串文字表达式"string"具有“{元素数组char”(6个字符加0个终结符)。在C中,类型为“{-1}}的N元素数组”的表达式将被转换为“指向T的指针”的表达式,它的值将是地址当数组表达式是T或一元sizeof运算符的操作数时,数组中第一个元素之外,或者是用于初始化另一个数组的字符串文字在声明中。

所以当你写

&

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

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

作为安全措施,大多数人明确声明指针为ptr

const char *

这样您就无法通过const char *ptr = "string"; 修改字符串内容。请注意,C ++在字符串文字类型为“ptr数组”方面有所不同,因此无论如何这些表达式都将转换为const char

  

我问的原因是因为我读过它的形式看起来好像有什么东西在它之后,就像char * myvariable那样它应该是一个指针。

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

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

*

表达式 x = *p; 的类型为*p,因此变量 int的声明为

p

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

*p

它被解释为

*

答案 2 :(得分:0)

通过撰写char *myvariableint foodouble blahvoid (*funcptr)(void),您声明某种类型的变量。变量的类型指定存储在该变量中的内容:指针,数字或结构。

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

答案 3 :(得分:0)

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

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

要使用&myvariable

获取您必须取消引用的值

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

答案 4 :(得分: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中使用相同的语法声明它,这有点棘手。但这里有一些例子:

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中,函数总是按值调用:复制函数的参数。因此,要从函数内部修改某些内容,您需要传递一个指针;指针被复制,但指针的值用于查找要修改的变量。

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