C的指针和字符串

本文探讨了C语言中指针和字符串的概念。指针作为右值给出变量的地址,而字符串实际上是字符数组,以''结尾。数组名是常量指针,不能改变,而指针可以指向不同地址。在C++中,数组名总是常量表达式。字符串字面量在内存中具有固定地址,不可直接赋值给指针,因为它们是字符数组。指针仅包含地址,不具备变量的完整功能。数组由一系列相同类型的元素组成,其名作为指针常量,指向首元素地址。
摘要由CSDN通过智能技术生成

在C语言中,左值为寻找变量的地址,右值为寻找变量的值

有如下程序:

#include <stdio.h>
int main()
{
	int i = 5;
	int *p = &i;
	scanf("%d",p);
	printf("%d",*p);
}

Output:

8
8

p做右值输出p的值,即i的地址。

又有:

char *s = "kkk";
printf("%s",s);

output:

kkk

为什么呢?明明s是指针只能指向一个地址。
双引号是一个特殊的符号。
“”号不是字符串的一部分,但它告知编译器它括起来的是字符串。
字符串在计算机中的表示为3方面:

  • 创建一个数组(数组在创建时必须有大小)
  • 把字符串中的字符逐个放入数组
  • 在末尾添加\0(NULL字符,但占一个char存储单元)

    因此,s实际指向了一个字符-数组-指针(即数组的地址),然后依次读取,到‘\0’结束
    而’‘字符与“”字符串的不同也体现在‘’只有一个单字符没有’\0’标识结束因为也不需要,而“”必须有结束字符’\0’空字符。

    同时数组名是指针常量(ElemType * const p),其指向地址值不能被修改,不同于(const ElemType * p)常量指针指向一个常量,地址值可修改。否则数
    组原意义会消失,数组将无法标识确切的数的集合,数组的核心在于组合正确,而不是说鱼的种类然后指向鸟的种类,它的声明应该是不加变化的,因为如果真的要这样做完全可以用其他指针指向,而指向的胡乱修改会造成问题。

    同时C中的数组名,是否常量表达式要视其存储连续性而定,全局数组、静态数组名都是常量表达式,而自动数组名不是。在C++中,由于不再规定常量表达式必须是编译期的,因此C++的数组名都是常量表达式。
    我通常使用cpp。

    数组必须要有一个真正的标记名。数组属于派生类型。

    同时,数组名既可以是指针常量,也可以不是指针常量,它是一种特别的数据类型。

    同时可知s[2]等同*(s+2),其与s+2有所不同,s+2仅仅只是指针(即地址)。

    updated in 11/16/2019
    可笑的程序:

    char *u;
    scanf("%s",u);
    

    u是未初始化的指针,可能指向任何地址。而scanf()要把信息拷贝至参数指定的地址上。

    char *u;
    u = "String";
    

    这样是可以的。u的地址被初始化,因为"“符具有数组属性,既有指针地址更有各个元素。
    总结:
    scanf()只为得到值,而指针亦没有真正的地址。”"符即提供了地址也提供了值,因为字符串相当于一个数组(派生结构)。一个被声明的数组既有地址也有值。

    通过多次打印字符串首字符的值,我们可以看到其地址是动态分配的。"“括起来的内容被称为字符串字面量(string literal),也叫字符串常量"string constant”,其相当于字符串数组名。

    	char *u;
    	u = "ooo";
    	char *c = "ooo";
    	printf("%p %p",u,c);
    

    输出:

    00403024 00403024
    

    "ooo"是同一个字符数组,地址已经被储存固定(静态存储类型),在整个程序生命周期存在。

    	char u[3];
    	u = "ooo";
    	char c[3] = "ooo";
    	printf("%p %p",u,c);
    

    error: assignment to expression with array type
    u = “ooo”;
    字符串是一个字符数组,数组需要有数组名,字符串的数组名就是其字面量。字符串是比数组更高级的类型,应该属于数组的派生类型(自己思索)。

    指针的本质即是地址,char name[80]即是分配了一个80char字符大小的块空间,其名称name是有地址的,因为80char字符大小需要首地址。
    “”是创建一个字符数组的标记,即字符串“%s”是字符数组的标记。而指针是一个4字节大小的指向某个特定位置的变量。
    还记得变量的指针就是变量的地址吗?指针只有地址,它不具备变量的完全功能,没有真实值的属性,地址和值是一个变量的两种形态。
    数组是由数据类型相同的一系列元素组成。由于元素是变量,所以数组是有具体值的——同时,数组还具有数组名的指针,数组1元值可为*p,p[0],地址可为p,&p[0].

    #include <stdio.h>
    int main()
    {
    	int i[5] = {1,5,6,7,9};
    	printf("%p %p\n",i,&i[0]);
    	printf("%d %d\n",*i,i[0]);
    }
    

    输出:

    0060FEEC 0060FEEC
    1 1
    
    

    可见数组是由数组名的指针和分配的连续内存的变量组合而成。
    数组名的指针即数组首元素的地址,其值为常量不会改变。
    如:

    #include <stdio.h>
    int main()
    {
    	int i[5] = {1,2,3,4,5};
    	i++;
    }
    

    此程序无法通过编译,error: lvalue required as increment operand.左值需要是一个可增的操作数,i不是变量,它表示i[0]的地址。
    如果用一个指针int型变量p指向i,将也无法修改其值。p++相当于i的地址加一个int变量的大小。其是指向了一个常量+sizeof(int)的常量。

    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值