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语言时,对一维数组和指针的理解应该是自信的,但是,我在学习过程中,看到网上一些博文,发现即便是参加工作的一些专业编程人员,突然碰到二维数组和指针的问题时,也可能会遇到难以处理的诡异问题 ...
随机推荐
- C# string[,]与string[][]的区别
对于这两者的区别: 1.入门:string[,]可读可写,而string[][]与string[]相同,不可对第二位进行写操作 static void Main(string[] args) { // ...
- 说说Audition消除歌曲中的人声
今天再说说消除人声,音乐中人声的消除有多种方法,但都很难完全消除,而且效果越好越难消除,一首音效极佳的立体声歌曲是无法完全消除人声的.本人常用的是以下三种方法.第1种如下图,此方法简单,但是完成后变成 ...
- .net中创建xml文件
//创建空的XML文档 XmlDocument xmldoc = new XmlDocument(); xmldoc.LoadXml("<?xml version='1.0' enco ...
- 简单三步-实现dede站内搜索功能
第一步:找到对应的搜索模板的代码 我们都知道,dede有自带的搜索功能,我们只要找到对应的模板,然后把我们想要的代码拿出来就行了.具体如下: 首先进入templets-->default--&g ...
- HDU-3308 LCIS(区间合并)
题目大意:给一个整数序列,m次询问,每次询问某个区间中最长连续上升子序列的长度. 题目分析:线段树区间合并.维护以区间左端开头的.以区间右端点结尾的和区间最长的上升连续序列. 代码如下: # incl ...
- Metasploit连接postgres数据库
操作环境为Kali虚拟机 root@kali:~# apt-get install postgresql 启动服务 root@kali:~# service postgresql start [ ok ...
- Unity学习资源
NGUI文档及视频: http://www.tasharen.com/forum/index.php?topic=6754 动态更新的解决方案: http://game.ceeger.com/foru ...
- CUDA Thread Indexing
1D grid of 1D blocks __device__ int getGlobalIdx_1D_1D() { return blockIdx.x *blockDim.x + threadIdx ...
- Android 编程下去除 ListView 上下边界蓝色或黄色阴影
默认的情况下,在 ListView 滑动到顶部或者是底部的时候,会有黄色或者蓝色的阴影出现.在不同的版本上解决的方法是不同的,在 2.3 版本之前可以在 ListView 的属性中通过设置 andro ...
- FSM, VISIBILITY MAP AND VACUUM
Update: Heikki’s slides are here! Heikki Linnakangas gave a presentation this past Sunday at FOSDEM ...