怎样将函数内部的字符串数组通过函数参数传递出来?

seai 2017-05-21 11:53:39
下面做法,编译运行结果是正常的,但,直接把内部变量的地址传递出去,在外面访问是不是不是安全?
我理解为,函数内部地址空间的内容,出了函数后就不保证不被人修改了。这样虽然能访问到,但值很可能不是期望的?


#include <stdio.h>
int foo(const char *** s)
{
const char* s1[]={"abc","efg"};
*s=&s1;
return 0;
}

int main(int argc, char ** argv)
{
const char **s;
foo(&s);
printf(" %s %s ", s[0], s[1]); //输出结果: abc efg
}
...全文
880 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
ZacCchary 2017-06-19
  • 打赏
  • 举报
回复
引用 18 楼 seai 的回复:
这个解比较靠谱。 补充问一句:如果里面不是字符串字面值,而是字符串变量,那么,其中每一个元素都要重新分配堆空间吧。 [quote=引用 17 楼 fjzqabx 的回复:]

#if 1

void get_ptr(char ***save)
{
	//argv数组中的每个元素都是指向rodata段的指针,rodata段中数据的生命周期等同程序生命周期
	char *argv[] = {"hello", "C", "world"};

	*save = argv;//argv本身就是字符指针数组中元素的首地址,直接赋给二级字符指针即可
}

int main(void)
{
	char **save = NULL;
	
	get_ptr(&save);
	
	//完全不必担心save数组中的元素出了get_ptr函数被释放,除非你的程序走到头了.
	printf("%s\t%s\t%s\n", save[0], save[1], save[2]);

	return 0;
}

#endif
[/quote]
引用 18 楼 seai 的回复:
这个解比较靠谱。 补充问一句:如果里面不是字符串字面值,而是字符串变量,那么,其中每一个元素都要重新分配堆空间吧。 [quote=引用 17 楼 fjzqabx 的回复:]

#if 1

void get_ptr(char ***save)
{
	//argv数组中的每个元素都是指向rodata段的指针,rodata段中数据的生命周期等同程序生命周期
	char *argv[] = {"hello", "C", "world"};

	*save = argv;//argv本身就是字符指针数组中元素的首地址,直接赋给二级字符指针即可
}

int main(void)
{
	char **save = NULL;
	
	get_ptr(&save);
	
	//完全不必担心save数组中的元素出了get_ptr函数被释放,除非你的程序走到头了.
	printf("%s\t%s\t%s\n", save[0], save[1], save[2]);

	return 0;
}

#endif
[/quote]对的,因为字符指针数组的每个元素都只是一个4字节大小的指针,要给每个指针指定一个字符串(不论常量还是变量)的指向,按照你的意思字符串需要全局段的区域只有字符串常量区和堆区动态分配出来的内存.
seai 2017-06-15
  • 打赏
  • 举报
回复
这个解比较靠谱。 补充问一句:如果里面不是字符串字面值,而是字符串变量,那么,其中每一个元素都要重新分配堆空间吧。
引用 17 楼 fjzqabx 的回复:

#if 1

void get_ptr(char ***save)
{
	//argv数组中的每个元素都是指向rodata段的指针,rodata段中数据的生命周期等同程序生命周期
	char *argv[] = {"hello", "C", "world"};

	*save = argv;//argv本身就是字符指针数组中元素的首地址,直接赋给二级字符指针即可
}

int main(void)
{
	char **save = NULL;
	
	get_ptr(&save);
	
	//完全不必担心save数组中的元素出了get_ptr函数被释放,除非你的程序走到头了.
	printf("%s\t%s\t%s\n", save[0], save[1], save[2]);

	return 0;
}

#endif
ZacCchary 2017-05-23
  • 打赏
  • 举报
回复

#if 1

void get_ptr(char ***save)
{
	//argv数组中的每个元素都是指向rodata段的指针,rodata段中数据的生命周期等同程序生命周期
	char *argv[] = {"hello", "C", "world"};

	*save = argv;//argv本身就是字符指针数组中元素的首地址,直接赋给二级字符指针即可
}

int main(void)
{
	char **save = NULL;
	
	get_ptr(&save);
	
	//完全不必担心save数组中的元素出了get_ptr函数被释放,除非你的程序走到头了.
	printf("%s\t%s\t%s\n", save[0], save[1], save[2]);

	return 0;
}

#endif
wallesyoyo 2017-05-23
  • 打赏
  • 举报
回复
引用 8 楼 seai 的回复:
[quote=引用 7 楼 cfjtaishan 的回复:] [quote=引用 6 楼 seai 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?[/quote] 为了能在main函数里得到字符串的地址,方法就是加static const char *s1[];原因是s1是局部变量,生命周期是函数内,函数调用结束,s1的生命就随着结束,加了static,那么它的生命周期就是整个程序,程序结束s1也随着释放。 当然也有其他方法,就是在堆栈上申请s1(2个指针大小空间),因为堆上的空间不会随着函数释放而释放,它可以在main函数里释放,前提是main函数尤其申请的堆上空间的首地址。[/quote] 静态方法不是很好的选择,说到底我要给这个C++接口做一个C的封装: ============================================= int segmentor_segment(void *segmentor, const std::string &line, std::vector<std::string> &words) 功能:调用分词接口。 参数: 参数名 参数描述 void * segmentor 分词器的指针 const std::string & line 待分词句子 std::vector<std::string> & words 结果分词序列 返回值: 返回结果中词的个数。 ============================================= 要把words的数据返回给C使用。words有可能很大,每个token空间都是static的话应该是不可行的。 [/quote] 你这个可以搞个局部变量的数组,传给函数作为函数的返回值额。比如 words[MAX_WORD_COUNT][MAX_WORD_LENGTH],一个句子的词的个数,和每个词的长度肯定是有上界的吧,就用这种数组传参进入接收函数的输出。
赵4老师 2017-05-22
  • 打赏
  • 举报
回复
引用 12 楼 zhao4zhong1 的回复:
这个世界上根本就没有那么多“不确定”。 在现实世界中,除时间和空间可能是无限的以外,其它任何事物都是有限的。
参考下面:
//使用动态分配
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int i,L;
char *p;
void main() {
    for (i=0;i<20000;i++) {
        L=rand();
        p=malloc(L);
        if (NULL==p) {
            printf("malloc error!\n");
            continue;
        }
        memset(p,0,L);
        free(p);
    }
}
//不使用动态分配
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#define MAXLEN 30000
int i,L;
char buf[MAXLEN];
char *p;
void main() {
    p=&buf[0];
    for (i=0;i<20000;i++) {
        L=rand();
        if (L>MAXLEN) {
            printf("L>MAXLEN==%d, ignore spilth.\n",MAXLEN);
            L=MAXLEN;
        }
        memset(p,0,L);
    }
}
个人倾向不使用动态分配。
自信男孩 2017-05-22
  • 打赏
  • 举报
回复
引用 8 楼 seai 的回复:
[quote=引用 7 楼 cfjtaishan 的回复:] [quote=引用 6 楼 seai 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?[/quote] 为了能在main函数里得到字符串的地址,方法就是加static const char *s1[];原因是s1是局部变量,生命周期是函数内,函数调用结束,s1的生命就随着结束,加了static,那么它的生命周期就是整个程序,程序结束s1也随着释放。 当然也有其他方法,就是在堆栈上申请s1(2个指针大小空间),因为堆上的空间不会随着函数释放而释放,它可以在main函数里释放,前提是main函数尤其申请的堆上空间的首地址。[/quote] 静态方法不是很好的选择,说到底我要给这个C++接口做一个C的封装: ============================================= int segmentor_segment(void *segmentor, const std::string &line, std::vector<std::string> &words) 功能:调用分词接口。 参数: 参数名 参数描述 void * segmentor 分词器的指针 const std::string & line 待分词句子 std::vector<std::string> & words 结果分词序列 返回值: 返回结果中词的个数。 ============================================= 要把words的数据返回给C使用。words有可能很大,每个token空间都是static的话应该是不可行的。 [/quote] 不要把静态方法和静态变量混淆了,静态方法是static限制函数的,静态变量是在静态数据段上存放,对数组s1加static是改变s1的生命周期,这样可以在main函数里,在foo调用结束后s1没有被释放。
赵4老师 2017-05-22
  • 打赏
  • 举报
回复
这个世界上根本就没有那么多“不确定”。 在现实世界中,除时间和空间可能是无限的以外,其它任何事物都是有限的。
seai 2017-05-22
  • 打赏
  • 举报
回复
引用 10 楼 zhao4zhong1 的回复:
在整个程序初始化时分配该程序将要用到的所有空间; 在整个程序退出前释放该程序在初始化时分配的所有空间。
但这样一来,接口会返回多少字符串是不确定的,所需的空间也就不确定的,和开始就分配好空间呢?
赵4老师 2017-05-22
  • 打赏
  • 举报
回复
在整个程序初始化时分配该程序将要用到的所有空间; 在整个程序退出前释放该程序在初始化时分配的所有空间。
yangyunzhao 2017-05-22
  • 打赏
  • 举报
回复
引用 6 楼 seai 的回复:
[quote=引用 5 楼 cfjtaishan 的回复:] foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?[/quote] 比较保险的做法是

char * getstr()
{
 char * pret = new char[XXX];
......;
return pret;
}
void release(char *& ptr)
{
delete []ptr;
ptr = NULL;
}
这样跨DLL使用也没有问题
seai 2017-05-21
  • 打赏
  • 举报
回复
引用 3 楼 zhao4zhong1 的回复:
业界的通行做法是传指向大量共享数据的指针。
所以,技术上,我上面的做法是没有问题的咯。在函数外部访问的时候,指针所指向的那些数据,我不需要担心被释放?
赵4老师 2017-05-21
  • 打赏
  • 举报
回复
业界的通行做法是传指向大量共享数据的指针。
seai 2017-05-21
  • 打赏
  • 举报
回复
引用 1 楼 zhao4zhong1 的回复:
请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢?
亲,谢谢你的回复。 首先,我最关注的还是我的上面的担心是否正确,还是说,可以技术上是可行可靠的。 此次,我demo的这段代码,之所以这样做,其实恰是因为,我调用的一个c++动态库接口,它的返回值表示成功与否,实际的数据是用参数传出的。我需要给它做一个C的封装,然后就有了上面的路子。如果有更好的方法,请明示。本人C/C++只能算业余的。 多谢了。
赵4老师 2017-05-21
  • 打赏
  • 举报
回复
请那些喜欢将数组作为函数参数传来传去或作为函数返回值的码农思考一下为什么不把整个互联网内容当作函数参数传来传去或作为函数返回值呢?
paschen 2017-05-21
  • 打赏
  • 举报
回复
s1数组本身是局部变量,函数结束后就销毁了,结果正确只能说明运气好 字符串"abc"是在常量区,可以从函数返回指向常量字符串的指针 要限制函数外修改,可以限定指针类型,让指针指向的字符串为常量
seai 2017-05-21
  • 打赏
  • 举报
回复
引用 7 楼 cfjtaishan 的回复:
[quote=引用 6 楼 seai 的回复:] [quote=引用 5 楼 cfjtaishan 的回复:] foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?[/quote] 为了能在main函数里得到字符串的地址,方法就是加static const char *s1[];原因是s1是局部变量,生命周期是函数内,函数调用结束,s1的生命就随着结束,加了static,那么它的生命周期就是整个程序,程序结束s1也随着释放。 当然也有其他方法,就是在堆栈上申请s1(2个指针大小空间),因为堆上的空间不会随着函数释放而释放,它可以在main函数里释放,前提是main函数尤其申请的堆上空间的首地址。[/quote] 静态方法不是很好的选择,说到底我要给这个C++接口做一个C的封装: ============================================= int segmentor_segment(void *segmentor, const std::string &line, std::vector<std::string> &words) 功能:调用分词接口。 参数: 参数名 参数描述 void * segmentor 分词器的指针 const std::string & line 待分词句子 std::vector<std::string> & words 结果分词序列 返回值: 返回结果中词的个数。 ============================================= 要把words的数据返回给C使用。words有可能很大,每个token空间都是static的话应该是不可行的。
自信男孩 2017-05-21
  • 打赏
  • 举报
回复
引用 6 楼 seai 的回复:
[quote=引用 5 楼 cfjtaishan 的回复:] foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?[/quote] 为了能在main函数里得到字符串的地址,方法就是加static const char *s1[];原因是s1是局部变量,生命周期是函数内,函数调用结束,s1的生命就随着结束,加了static,那么它的生命周期就是整个程序,程序结束s1也随着释放。 当然也有其他方法,就是在堆栈上申请s1(2个指针大小空间),因为堆上的空间不会随着函数释放而释放,它可以在main函数里释放,前提是main函数尤其申请的堆上空间的首地址。
seai 2017-05-21
  • 打赏
  • 举报
回复
引用 5 楼 cfjtaishan 的回复:
foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
你的解答比较清晰,我翻了翻网上文章,确实是这样的。 所以,正确的做法是: a、在函数内分配堆空间,数据复制到对空间,由指针返回使用后释放吗? 还是, b、在调用前分配好空间,函数内通过指针把数据写入到先前分配好的空间? a的问题在于分配空间和释放空间不在一处,难免犯差错 b的问题在于不知道函数内的数据有多大、需要分配多少空间承载数据 这方面的“最佳实践”,有示范的代码展示一下吗?
自信男孩 2017-05-21
  • 打赏
  • 举报
回复
foo的操作获得的s1的地址是没有意义的,得到的结果也是未定义的。因为s1是在foo函数栈上申请的局部变量指针数组,foo调用结束后,s1指针数组就会被释放,那么你得到的s1的地址自然就没有意义了,即使你得到的字符串是对的,因为可能foo释放之后的空间尚未被新的函数申请。所以,这个是未定义的。
目 录 序言 前言 第1章 程序设计与算法 1 1.1 程序设计语言的发展 1 1.2 C语言的特点 2 1.2.1 C语言是中级语言 2 1.2.2 C语言是结构化语言 3 1.2.3 C语言是程序员的语言 3 1.3 C语言的程序结构 4 1.3.1 基本程序结构 4 1.3.2 函数库和链接 6 1.3.3 开发一个C程序 7 1.3.4 C语言的关键字 7 1.4 算法 8 1.4.1 流程图与算法的结构化描述 9 1.4.2 用N-S图描述算法 12 1.4.3 用PAD图描述算法 13 第2章 数据类型、运算符和表达式 14 2.1 C语言的数据类型 14 2.2 常量与变量 15 2.2.1 标识符命名 15 2.2.2 常量 16 2.2.3 变量 16 2.3 整型数据 16 2.3.1 整型常量 16 2.3.2 整型变量 17 2.4 实型数据 18 2.4.1 实型常量 18 2.4.2 实型变量 18 2.5 字符型数据 19 2.5.1 字符常量 19 2.5.2 字符串常量 19 2.5.3 转义字符 20 2.5.4 符号常量 20 2.5.5 字符变量 21 2.6 运算符 22 2.6.1 算术运算符 22 2.6.2 自增和自减 22 2.6.3 关系和逻辑运算符 23 2.6.4 位操作符 24 2.6.5 ?操作符 26 2.6.6 逗号操作符 27 2.6.7 关于优先级的小结 27 2.7 表达式 28 2.7.1 表达式中的类型转换 28 2.7.2 构成符cast 29 2.7.3 空格与括号 29 2.7.4 C语言中的简写形式 29 第3章 程序控制语句 31 3.1 程序的三种基本结构 31 3.2 数据的输入与输出 31 3.2.1 scanf()函数 31 3.2.2 printf()函数 33 3.2.3 getchar()函数与putchar()函数 36 3.2.4 程序应用举例 37 3.3 条件控制语句 38 3.3.1 if 语句 38 3.3.2 switch 语句 43 3.3.3 程序应用举例 45 3.4 循环控制语句 46 3.4.1 while语句 47 3.4.2 do... while 语句 49 3.4.3 for 语句 50 3.4.4 break与continue语句 53 3.4.5 程序应用举例 54 第4章 函数 57 4.1 函数说明与返回值 57 4.1.1 函数的类型说明 57 4.1.2 返回语句 58 4.2 函数的作用域规则 60 4.2.1 局部变量 60 4.2.2 全局变量 61 4.2.3 动态存储变量 62 4.2.4 静态存储变量 63 4.3 函数的调用与参数 63 4.3.1 形式参数与实际参数 64 4.3.2 赋值调用与引用调用 64 4.4 递归 64 4.5 实现问题 66 4.5.1 参数和通用函数 66 4.5.2 效率 66 4.6 函数库和文件 67 4.6.1 程序文件的大小 67 4.6.2 分类组织文件 67 4.6.3 函数库 67 4.7 C语言的预处理程序与注释 67 4.7.1 C语言的预处理程序 68 4.7.2 #define 68 4.7.3 #error 69 4.7.4 # include 69 4.7.5 条件编译命令 70 4.7.6 #undef 72 4.7.7 #line 73 4.7.8 #pragma 73 4.7.9 预定义的宏名 73 4.7.10 注释 73 4.8 程序应用举例 74 第5章 数组 78 5.1 一维数组 78 5.1.1 向函数传递一维数组 78 5.1.2 字符串使用的一维数组 79 5.2 二维数组 80 5.2.1 二维数组的一般形式 80 5.2.2 字符串数组 84 5.3 多维数组 85 5.4 数组的初始化 85 5.4.1 数组初始化 85 5.4.2 变长数组的初始化 86 5.5 应用程序举例 87 第6章 指针 91 6.1 指针与指针变量 91 6.2 指针变量的定义与引用 92 6.2.1 指针变量的定义 92 6.2.2 指针变量的引用 93 6.3 指针运算符与指针表达式 94 6.3.1 指针运算符与指针表达式 94 6.3.2 指针变量作函数的参数 95 6.4 指针与数组 96 6.4.1 指针与一维数组 97 6.4.2 指针与二维数组 99 6.4.3 数组指针作函数的参数 102 6.4.4 指针与字符数组 108 6.5 指针的地址分配 111 6.6 指针数组 112 6.7 指向指针的指针 118 6.8 main函数的参数 121 第7章 结构体与共用体 125 7.1 结构体类型变量的定义和引用 125 7.1.1 结构体类型变量的定义 126 7.1.2 结构体类型变量的引用 127 7.1.3 结构体类型变量的初始化 127 7.2 结构体数组的定义和引用 129 7.3 结构体指针的定义和引用 135 7.3.1 指向结构体类型变量的使用 135 7.3.2 指向结构体类型数组的指针的 使用 136 7.4 链表的建立、插入和删除 138 7.4.1 单链表 139 7.4.2 单链表的插入与删除 141 7.5 共用体 149 7.5.1 共用体的定义 149 7.5.2 共用体变量的引用 150 第8章 输入、输出和文件系统 153 8.1 缓冲文件系统 153 8.1.1 文件的打开与关闭 153 8.1.2 文件的读写 155 8.1.3 随机读写文件 163 8.2 非缓冲文件系统 166 8.3 文件系统应用举例 167 第9章 实用编程技巧 170 9.1 图形应用技巧 170 9.1.1 显示适配器类型的自动测试 170 9.1.2 屏幕图像的存取技巧 179 9.1.3 屏幕显示格式的控制方法 181 9.1.4 使图形软件脱离BGI的方法 182 9.1.5 拷贝屏幕图形的方法 183 9.1.6 随意改变VGA显示器显示颜色的 技巧 185 9.1.7 用随机函数实现动画的技巧 187 9.1.8 用putimage 函数实现动画的技巧 189 9.2 菜单设计技术 191 9.2.1 下拉式菜单的设计 191 9.2.2 选择式菜单的设计 194 9.2.3 实现阴影窗口的技巧 195 9.3 音响技巧 197 9.3.1 音乐程序设计 197 9.3.2 自动识谱音乐程序 200 9.3.3 实现后台演奏音乐的技巧 203 第10章 C++入门 205 10.1 面向对象的概念 205 10.1.1 面向对象的程序结构 205 10.1.2 C++的类 206 10.2 C++的输入与输出 207 10.3 类与对象 208 10.3.1 类的定义与对象的引用 209 10.3.2 构造函数与析构函数 211 10.3.3 函数重载 215 10.3.4 友元 216 10.4 对象指针 219 10.5 派生类与继承类 225 10.5.1 单继承的派生类 225 10.5.2 多继承的派生类 233 附录A 常用字符与ASCII代码对照表 238 附录B 习题 239

69,369

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧