C语言中的数组和指针以及字符串
数组名同时也是该数组首元素的地址,而指针提供了一种用来使用地址的符号方法,因此指针能够很有效地处理数组。
将一个整数加给指针,这个整数会和指针所指类型的字节数相乘,然后所得的结果会加到初始地址上
date + == &date[]; // 相同的地址
*(date + ) == date[]; // 相同的值
在函数原型或函数定义头的场合中(并且也只有在这两种场合中),可以用int ar[]代替int* ar,处理数组的函数实际上是使用指针做为参数的
int sum(int* ar, int n);
int sum(int ar[], int n); // 二者在此处等价
无论在任何情况下,形式int* ar都表示ar是指向int的指针。形式int ar[]也可以表示ar是指向int的指针,但只是在声明形式参量时才可以这样使用。使用第二种形式可以提醒读者ar不仅指向一个int数值,而且它指向的这个int是一个数组中的元素。
C语言中的字符串
字符串是C里面最有用、最重要的数据类型之一。C语言中的字符串是以空字符('\0')结尾的char数组。
下面两个都声明str是一个指向给定字符串常量的指针:
char str[] = "Klingon";
const char* str = "Klingon";
在两种情况下,都是被引用的字符串本身决定了为字符串预留的存储空间大小。尽管如此,这两种形式并不完全相同。
数组形式(str[])在计算机内存中被分配一个有8个元素的数组(其中每个元素对应一个字符,还有一个附加的元素对应结束的空字符'\0'),每个元素都被初始化为相应的字符。通常,被引用的字符串存储在可执行文件的数据段部分;当程序被加载到内存中时,字符串也被加载到内存中,位于静态存储区;在程序开始运行后才为数组分配存储空间,这时候把被引用的字符串复制到数组中。
指针形式(* str)也在静态存储区为字符串预留8个元素的空间。一旦程序开始运行,还要为指针变量str另外预留一个存储位置,以在该指针变量中存储字符串的地址,指针变量str初始时指向字符串的第一个字符。
总之,数组初始化是从静态存储区把一个字符串复制给数组,而指针初始化只是复制字符串的地址。
char* str = "Klingon";
str[] = 'F'; // 是否允许?
您的编译器可能会允许上面的情况,但按照当前的C标准,编译器不应该允许这样做。这种语句可能会导致内存访问错误。原因在于编译器可能选择内存中的同一个单个的拷贝,来表示所有相同的字符串常量。代码如下:
char* str = "Klingon";
str[] = 'F'; // ok?
printf("Klingon");
printf(":Beware the %ss!\n","Klingon");
如果编译器使用这种单个拷贝表示法并且允许把str[0]改为'F'的话,那将会影响到所有对这个字符串的使用。于是打印字符串"Klingon"的语句实际将会显示"Flingon",上述代码运行结果如下:
Flingon:Beware the Flingons!
实际上,有些个编译器确实是按这种容易混淆的方式工作,而其他的一些则会产生程序异常中断(如Microsoft Visual Studio)
因此,建议的做法是初始化一个指向字符串常量的指针时使用const修饰符:
const char* str = "Klingon"; // 推荐用法
而用一个字符串常量来初始化一个非const的数组,则不会导致此类问题,因为数组从最初的字符串得到了一个拷贝
char str[] = "Klingon";
str[] = 'F'; // 合法
C语言中的数组和指针以及字符串的更多相关文章
- C语言中的数组与指针
1. 数组的初始化 数组的初始化方法有很多,常用的方法有 定义时初始化 ]={,,}; 或 ]={}; //未初始化的元素全为0: 定义后遍历赋值初始化 int arr[3]; for(int i=0 ...
- Go 语言中的数组是一种 值类型(不像 C/C++ 中是指向首元素的指针)
the-way-to-go_ZH_CN/07.1.md at master · Unknwon/the-way-to-go_ZH_CN https://github.com/Unknwon/the-w ...
- go语言中的数组切片:特立独行的可变数组
go语言中的数组切片:特立独行的可变数组 初看go语言中的slice,觉得是可变数组的一种很不错的实现,直接在语言语法的层面支持,操作方面比起java中的ArrayList方便了许多.但是在使用了一段 ...
- 【VS开发】【编程开发】【C/C++开发】结构体中的数组与指针的内存分配情况说明
[VS开发][编程开发][C/C++开发]结构体中的数组与指针的内存分配情况说明 标签:[VS开发] [编程开发] 主要是疑惑在结构体定义的数组的内存空间与指针动态分配的内存空间,在地址上连续性.以及 ...
- Go语言中底层数组和切片的关系以及数组扩容规则
Go语言中底层数组和切片的关系以及数组扩容规则 demo package main import ( "fmt" ) func main() { // 声明一个底层数组,长度为10 ...
- DELPHI数组,指针,字符串转换的例子
关于数组,指针,字符串转换的例子 var aa: array [0..5] of Char; bb:Pointer; cc:string; dd:PChar; procedure ...
- C语言核心之数组和指针详解
指针 相信大家对下面的代码不陌生: int i=2; int *p; p=&i;这是最简单的指针应用,也是最基本的用法.再来熟悉一下什么是指针:首先指针是一个变量,它保存的并不是平常的数据,而 ...
- C语言学习004:数组与指针
在C语言中,字符串实际上就是字符数组,在内存中字符串"Shatner"存储的形式是这样的
- 关于c语言二维数组与指针的个人理解及处理办法。
相信大家在学习C语言时,对一维数组和指针的理解应该是自信的,但是,我在学习过程中,看到网上一些博文,发现即便是参加工作的一些专业编程人员,突然碰到二维数组和指针的问题时,也可能会遇到难以处理的诡异问题 ...
随机推荐
- myEclipse使用有感
一.破解 使用myeclipse 10.0版本:然后破解:(之前我使用10.7破解成功了,但是发布有问题) 二.发布注意事项 1.清理发布目录, 不要有多个项目搅和 2.js相关, 注意清理浏览器缓存 ...
- 内存回收,Dispose,Close,Finalie(C#中的析构函数)
NET中的资源分托管和非托管,所谓的托管是指CLR(通用语言运行时)中进行管理的资源,它可以由CLR自动进行内存回收. 也就是大家熟知的GC(垃圾回收机制). 而对于 非托管资源,比如数据库连接,CO ...
- 刻通云KeyTone Cloud测试
注:本文转自陈沙克的博客,原文见http://www.chenshake.com/carved-through-the-keytone-cloud-cloud-testing/ 一直都很希望有更多的O ...
- java zip文件的解压缩(支持中文文件名)
用的apache的ant包,下载导入即可.由于过程比较简单,直接上代码. 代码可直接复制使用. 如果想在android上使用,记得要在AndroidManifest.xml里添加权限: <use ...
- 从源码安装pip
由于服务器不能外网,只能通过从网上下载源码包的方式进行安装 下载地址 setuptools pip 安装步骤 首先需要安装setuptools,否则直接安装pip会提示没有setuptools $ t ...
- MAC OSX使用公钥方式登录Linux服务器并进行安全加固
登录Linux服务器的方式一般是使用ssh,直接使用密码登录既要记忆密码在输入过程中又有安全风险.所以本文将提供一个使用公钥登录的方式来解决输入密码的问题. 首先在mac上生成一个私钥.公钥对 首先, ...
- iOS学习笔记---oc语言第十天
内存管理高级 一 属性的内部实现原理 assign retain copy assign 下的属性内部实现 setter方法 @property(nonatomic,assign)NSS ...
- js 下载文件 window.location.href
window.location.href ="../../pages2/assessmentplan/exportPointAsessment.do?planId="+planId ...
- ZOJ 1188 DNA Sorting
原题链接 题目大意:给定一串字符串,查找字符串里字母逆序排列的对数,按照由少到多的顺序把所有字符串进行排列. 解法:用C++字符串string类的iterator,从每个字符串的起始开始,查找逆序字符 ...
- tyvj1022 - 进制转换 ——进制为负数
题目链接:https://www.tyvj.cn/Problem_Show.aspx?id=1022 #include <cstdio> #include <cstdlib> ...