数组和指针 - 2【C++ Primer 学习笔记 - 第四章】

指针和 const 限定符

double dheight = 100.5;
const double dprice = 10.5;
const double *pd = &dprice;	// pd 指向的 dprice 是const 的
pd = &dheight;	// pd 可以指向非const 的对象

int ierr = 0;
int *const curErr = &ierr;  // 指针 curErr, 是const的

const int iMsg = 10;
const int *const pmsg = &iMsg;	// 指针 和 指向的对象,都是const的




指针和 typedef。以下:ps,ps2,ps3 都是等价的。
原因是: const 限定符可以放在类型前,也可以放在类型后
就是说,         const string a;  
也可以写成: string const a;

typedef string * pstring;
string s("Hello");
const pstring ps = &s;
string *const ps2 = &s;  // 与上式,等价
pstring const ps3 = &s;  // 与上式,等价

此处,const 修饰的是 pstring 类型,也就是说,const 修饰的是指针。 typedef,不是简单的文本扩展!

因此,const pstring ps = &s;   其实等价于:   string *const ps = &s;



C风格字符串

字符串字面值 的类型,是字符常量的数组。
也就是,const char 类型的数组

C++ 从C语言 继承下来的一种通用结构就是 C风格字符串(C-style character string)
而,字符串面值,就是该类型的实例。

实际上,C风格字符串既不能归结为C语言的类型,也不能归结为C++语言的类型,
而是以空字符 null 结束的字符数组。


char ca1[] = {'C', '+', '+'};
char ca2[] = {'C', '+', '+', '\0'};	// C风格
char ca3[] = "C++";		// C风格,末尾自动加 null

const char *cp = "C++"; // C风格
char *cp1 = ca1;  // 
char *cp2 = ca2;  // C风格


C++ 通过 (const) char * 类型的指针,来操作C风格字符串。

const char *cp = "some value";
while(*cp)
{
	++cp;
}
如果 cp 指向的字符串数组没有null 字符,则,无法达到预期效果。
直到在内存中找到null 字符,循环才会终止。

操纵C风格字符串的标准库函数
strlen(s)返回s 长度,不包括结束符 null
strcmp(s1, s2)s1=s2,返回0; s1>s2,返回正数;  s1<s2,返回负数
strcat(s1, s2)将s2 连接到 s1,然后返回 s1
strcpy(s1, s2)将s2 复制给 s1,然后返回 s1
strncat(s1, s2, n)将s2 的前n个字符连接到 s1 后面,并返回 s1
strncpy(s1, s2, n)将s2 的前n个字符复制给 s1, 并返回 s1






注意:C风格字符串的操作容易出错。
通常使用标准库类型 string代替此类操作



动态数组

动态数组,不必在编译时知道其长度,可以是在运行时再确定数组长度。
每个程序,执行时都占用一块可用内存,用于存放动态分配的对象,
此内存称为:自由存储区(Free Store)或者 堆(Heap)
C++ 使用 new delete 来分配和释放 自由存储区。

string *sp = new string[10];
int *ip = new int[20];

size_t n = get_size();
int *ip3 = new int[n];

string *sp2 = new string[30]();
const int *ip2 = new const int[11]();

// char arr[0] 是错误的, 然而,动态分配时,长度可以是0,并返回非0 的指针,但该指针不能解引用
char *cp = new char[0];

delete [] ip3;


使用动态数组,通常是因为,编译时无法知道数组的准确长度。如:以下场景

const char *noerr = "success";
const char *err188 = "Error Code: 188";

const char *errorText;
if(errorFound)
	errorText = err188;
else
	errorText = noerr;

int dimension = strlen(errorText) + 1;
char *errMsg = new char[dimension];
strncpy(errMsg, errorText, dimension);


混合使用标准库类 string 和 C风格字符串
c_str () :返回C风格字符串的表示方法

string str("Hello");
const char *cp = str.c_str();  // C 风格字符串自动转换为,指向字符数组首地址的指针
// char *cp = str.c_str(); 错误,因为c_str() 返回的是 const char 类型的数组
// char *cp = str;   错误,无法使用 string 对象来初始化 字符指针

// str.c_str() 返回的数组未必永远有效。因为 str 有可能被修改。
// 因此,最好是复制 str.c_str() 返回的数组


string s("abcdefg");	
// char *a; 错误
// char *a = "x"; 
// 错误,"x"的内存是在栈上分配的,栈上的内存无法修改
// 返回的其实是 const char *,而不是 char *, 因此strcpy 将会无法写入,报错
char *a = new char[s.length()+1];
strcpy(a, s.c_str());




使用数组初始化 vector

const size_t array_size = 5;
int int_arr[array_size] = {88, 32, 13, 34, 65};

// 实际复制了 int_arr[1], int_arr[2], int_arr[3], int_arr[4]
vector<int> ivec(int_arr + 1, int_arr + array_size);


多维数组,即:数组的数组

int arr_first[2][3] = { {1, 2, 3}, {4, 5, 6} };

// 与上式等价
int arr_second[2][3] = {1, 2, 3, 4, 5, 6};

// 等价于:{ {1, 0, 0}, {2, 0, 0} }
int arr_third[2][3] = { {1}, {2} };

// 等价于:{ {1, 2, 0}, {0, 0, 0} }
int arr_fourth[2][3] = { 1, 2 };

// ip 是数组,长度为3,数组元素是,指向int 的指针
int *ip[3]; 

// ip_second 是指针,指向一个长度为3 的int 数组
int (*ip_second)[3];


typedef int int_array [3];
for(int_array *p_arr = arr_first; p_arr!=arr_first+2; ++p_arr)
	for(int *p_int = *p_arr; p_int!=*p_arr+3; ++p_int)
		*p_int = 100;
int c = arr_first[0][1];

..

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值