《C和C++代码精粹》——2.8 数组作为参数

2.8 数组作为参数

C和C++代码精粹
当你把数组作为参数传递给一个函数,正如所预期的那样,是传递了指向数组第一个元素的指针。因此,可以在调用的函数中永久地改变数组元素的值。在程序清单2.12的函数f中,地址&a[0]按值传递给指针b,因此表达式b[i]就和表达式a[i]完全是一样的了。不可能按值传一个完整的内置数组。

即使用数组符号定义了参数b,即:

int b[]

它同下面这种写法是完全一样的。

int *b

程序清单2.12 说明作为参数的数组实际上是指针

// array5.cpp: 数组作为参数
#include <iostream>
using namespace std;  

void f(int b[], size_t n)
{
    cout << "\n*** Entering function f() ***\n";
    cout << "b == " << b << endl;
    cout << "sizeof b == " << sizeof b << endl;
    for (int i = 0; i < n; ++i)
        cout << b[i] << ' ';
    b[2] = 99;
    cout << "\n*** Leaving function f() ***\n\n;
}  

main()
{
    int a[] = {0,1,2,3,4};
    size_t n = sizeof a / sizeof a[0];  

    cout << "a == " << a << endl;
    cout << "sizeof a == " << sizeof a << endl;
    f(a,n);
    for (int i = 0; i < n; ++i)
        cout << a[i] << ' ';
}  

//输出:
a == 0x0012ff78
sizeof a == 20  

*** Entering function f() ***
b == 0x0012ff78
sizeof b == 4
0 1 2 3 4
*** Leaving function f() ***  

0 1 99 3 4

而且,sizeof(b)==4,这是我的操作平台上指针的大小。我们无法在另一个函数中自动地决定一个数组编译时的大小。

指向数组元素的指针参数在文本处理中非常普遍。函数(str_cpy)就可以把一个字符串拷贝到另一个字符串中(除了无返回值外,它与strcpy一样):

void str_cpy(char *s1,const char *s2)
{
   while (*s1++  =*s2++);
}

while循环测试不是为了检测值相等,而是检测在赋值后(但是在自增之前)s1的值,循环在拷贝了结束符号‘0’后停止,表达式*p++是一个很常用的C/C++习惯方式。

习题 2.2

下面的语句通过一系列指针表达式修改字符串s,当顺序执行时每个表达式重新得到的是什么字符,最后的结果是什么?

char s[ ] = “ desolate”,*p = s;
*p++  = = ?
*(p++)= = ?
(*p)++= = ?
*++p  = = ?
*(++p)= =?
++*p  = = ?
++(*p)= =?
Strcmp(s,? ) = =0

(感谢Lincoln实验室的Chet Small提供了这个非常聪明的例子)。

本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。

时间: 2024-09-20 17:48:10

《C和C++代码精粹》——2.8 数组作为参数的相关文章

《C和C++代码精粹》——1.6 引用

1.6 引用 C和C++代码精粹由于C函数的参数是按值传递的,若传递大型结构给函数,既费时又占用空间.大多数C程序员使用指针来代替按值传递,例如,如果struct Foo是一个大型记录结构,可以采用如下方法: void f (struct Foo * fp) { /*通过fp来访问Foo结构*/ fp->x=- 等等. }``` 当然,为了使用这个函数,必须传递Foo结构的地址: struct Foo a;-f (&a);`C++的引用机制是符号上的便捷,这样做可以减少采用指针变量的显式间接

《C和C++代码精粹》——2.7 指针和一维数组

2.7 指针和一维数组 C和C++代码精粹 在程序清单2.7中,会注意到在传递数组 s 时并没有使用它的地址,这是因为C和C++在大多数表达式中把数组名转换成指向它第一个元素的指针.自1984年以来,我已经向成百上千的学生讲授了C和C++,我注意到了指针和数组,特别是指针和多维数组之间的关系造成很多迷惑. 这样说似乎很奇怪,但是C++确实不支持数组,至少C++不像支持第一类数据类型如整型或者甚至结构体那样支持数组.考虑以下的语句: int i=1,j; int a[4]={0,1,2,3},b[

《C和C++代码精粹》——2.9 字符串数组

2.9 字符串数组 C和C++代码精粹有两种方式来描述C风格的字符串数组:(1)指针数组:(2)二维数组.程序清单2.13中的程序说明了第一种方式.内存分布如下: 程序清单2.13 用指向字符的指针数组来实现字符串 // array6.cpp:粗糙的数组 #include <iostream> #include <cstring> using namespace std; main() { char* strings[] = {"now","is&qu

《C和C++代码精粹》——2.10 指针和多维数组

2.10 指针和多维数组 C和C++代码精粹实际上,在C++中没有多维数组!至少对多维数组没有直接的支持.人们通常把一个一维数组看作一个向量,把一个二维数组看作一个表或者矩阵,把一个三维数组看作一个长方体.然而,数组的几何模型使明智地使用高维数组变得很困难,取而代之的是C++支持"数组的数组"的概念.例如,如果一个一维的整型数组为 int a[4]={0,1,2,3}; 它是一个有索引的整数集合: 我们通常把它描述成一个向量: 对一个二维整型数组,如: int a[3][4]={{0,

《C和C++代码精粹》——2.11 更高深的内容

2.11 更高深的内容 C和C++代码精粹 我们可以很自然地得出以下结论:一个三维数组是二维数组的集合. int a[2] [3] [4]={{{0,1,2,3},{4,5,6,7},{8,9,0,1}}, {{2,3,4,5},{6,7,8,9},{0,1,2,3}}}; 这个数组的第一个元素是一个"二维数组" a[0](从技术上来说,a[0]是一个由3个含有4个整数的数组的数组),为了使指针与数组名a一致,定义: int (*p) [3] [4] = a; 程序清单2.16是一个应

《C和C++代码精粹》——1.10 操纵器

1.10 操纵器 C和C++代码精粹 当标识符 endl出现在一个输出流中时,一个换行字符就被插入并且流被刷新.标识符endl是操纵器的一个例子,即为了副效应而插入到流的一个对象.在〈iostream〉中被声明的系统预定义的操纵器列于表 1.3中.程序清单1.11里的程序在功能上与程序清单1.10的程序等价,但它是用操纵器来代替显式调用setf函数.操纵器经常可以使代码更为高效. 表1.3 简单的操纵器(〈iostream〉) 程序清单1.11 用操纵器改变数据基数 // base2.cpp:

《C和C++代码精粹》——2.12 指向函数的指针

2.12 指向函数的指针 C和C++代码精粹 一个指针可以指向函数也可以指向存储的对象.下面的语句声明fp是一个指向返回值为整型(int)的函数的指针: int(*fp)( ); *ftp的圆括号是必需的,没有它的语句 int *fp( ); 将fp声明为一个返回指向整型(int)指针的函数.这就是将星号与类型声明紧密相连的方式成为逐渐受人们欢迎的方式的原因之一. int fp(); //方式说明fp()返回一个指向整型的指针(int ) 当然,这种方式建议你通常应该每条语句只声明一个实体,否则

《C和C++代码精粹》导读

前言 C和C++代码精粹 本书适合于那些C和C++的职业程序员.假如你已熟悉这两种语言的语法和基本结构,这本书能够为你创建有效的.实用的程序提供实践性的指导.每一个代码范例或程序范例均标明行之有效的用法和技术,这些用法和技术对C/C++这两种重要编程语言的性能发挥起着重要的作用. 对于那些希望在工作中加强自身技术和提高效率的人来说,本书可以算是一本经验之谈.尽管目前人们对面向对象模式的推崇到了白热状态(本书也包括这方面的丰富内容),可是我没有理由不对C++的基础-C表示尊崇.我发现太多的程序开发

《C和C++代码精粹》——1.15 new和delete

1.15 new和delete C和C++代码精粹在C语言中为了用堆栈,需要计算出所要创建的对象的大小: struct Foo*fp =malloc(sizeof(struct Foo) ); 在C++中,运算符new用于计算出对象的大小: Foo*fp=new Foo; 在C语言中分配数组,需调用不同的函数. struct Foo*fpa= calloc(n,sizeof(struct Foo)); 在C++中,new运算符会知道数组的大小: Foo*fpa=new Foo[n]; 此外,运算