首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

为什么不能将`char**'传递给在C中使用`const char**`的函数?

在C语言中,char**const char**是两种不同的类型,虽然它们看起来很相似,但在语义上是不同的。因此,不能将char**传递给使用const char**的函数。

这是因为const关键字用于指示指针所指向的数据是只读的,而char**表示一个指向指针的指针,可以用于修改指针所指向的数据。如果将char**传递给使用const char**的函数,那么函数可能会尝试修改指针所指向的数据,这将导致类型不匹配的错误。

为了更好地理解这个问题,考虑以下示例代码:

代码语言:c
复制
void foo(const char** str) {
    *str = "Hello";
}

int main() {
    char* str = "World";
    foo(&str);
    return 0;
}

在这个例子中,foo函数接受一个const char**类型的参数,并尝试将其指向的数据修改为"Hello"。然而,main函数中的str变量是一个char*类型的指针,它指向一个字符串"World"。如果我们将&str传递给foo函数,编译器会发出警告或错误,因为这涉及将char**转换为const char**,这是不允许的。

为了解决这个问题,可以使用const char* const*类型来接受char**参数,并确保不会修改指针所指向的数据。修改后的示例代码如下:

代码语言:c
复制
void foo(const char* const* str) {
    // 无法修改指针所指向的数据
}

int main() {
    char* str = "World";
    foo(&str);
    return 0;
}

总结起来,不能将char**传递给使用const char**的函数,因为它们是不同的类型,涉及类型转换会导致错误。在这种情况下,可以使用const char* const*类型来接受char**参数,并确保不会修改指针所指向的数据。

腾讯云相关产品和产品介绍链接地址:

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

进程控制第二弹(进程程序替换)

只不过是拿老程序壳子执行新程序代码。 站在被替换进程角度:本质上是这个程序被加载到内存。使用exec系列函数加载,exec系列函数类似一种Linux上加载函数。...所以为什么上述现象,原来进程printf("testexec end! ...\n"); 没有执行原因是,调用execl函数后,去执行ls程序了,原来代码和数据被替换了。...使用所有的替换方法,并且认识函数参数含义 execl int execl(const char *path, const char *arg, ...); execl,l:list,列表 path:...需要执行路劲,需要带路劲 后面的参数:命令行怎么执行 例如: execl("/usr/bin/ls","ls","-l","-a",NULL); execv execv(const char...PATH,用户可以要执行路劲(但是文件名要),直接告诉要执行谁即可 if(id==0) { sleep(2); char* const argv

6810

C语言之指针(

"; char str2[] = "hello bit."; const char *str3 = "hello bit."; const char *str4 = "hello bit....3.使用 1.使用情景 一般情况下,用在一维数组时并不方便,所以我们一般多用在二维数组、多维数组。 注意:既然数组指针指向是数组,那数组指针存放应该是数组地址。...定义: void test(const char* str) { printf("%s\n", str); } int main() { //函数指针pfun void(*pf)(const char...如果你把函数指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向函数时,我们就说这是回调函数。...但由于篇幅原因,在这一篇文章仍不能将所有的知识全部总结完,因此后续还是会不断补充关于C语言中指针内容,希望大家继续支持。

71120

C语言——I 深入理解指针(一)

八、指针使用址调用 1、strlen模拟实现 strlen 返回类型为size_t 打印时为%zd 库函数strlen功能是求字符串⻓度,统计是字符串 \0 之前字符个数。...Swap1函数使⽤时候,是把变量本⾝直接传递给函数,这种调⽤函数⽅式我们之前函数时候就知道了,这种叫值调⽤。...那么就可以使⽤指针了,main函数中将a和b地址传递给Swap函数,Swap函数⾥边通过地址间接操作main函数a和b,并达到交换效果就好了。...址调用,可以让函数和主调函数之间建立真正联系,函数内部可以修改主调函数变量;所以未来函数只是需要主调函数变量值来实现计算,就可以采⽤值调⽤。...如果函数内部要修改主调函数变量值,就需要址调⽤。

8810

C语言之精华——指针详解(下)

当把数组名赋值给一个指针后,再对指针使用sizeof运算符,返回是指针大小。 这就是为什么我么将一个数组传递给一个函数时,需要另外用一个参数传递数组元素个数原因了。...「函数参数和指针」 C 语言中,实参传递给形参,是按值传递,也就是说,函数形参是实参拷贝份,形参和实参只是值上面一样,而不是同一个内存数据对象。...这就意味着:这种数据传递是单向,即从调用者传递给被调函数,而被调函数无法修改传递参数达到回效果。...,简单情况下是可以,但是如果返回值有其它用途(例如返回函数执行状态量),或者要回数据不止一个,返回值就解决不了了。...既然是存放在内存,那么函数也是有自己指针C 语言中,函数名作为右值时,就是这个函数指针。

53430

C语言】深入解开指针(二)

Debug 中使用 Release 版本中选择禁用 assert 就可以,像VS这样集成开发环境 Release 版本,直接就被优化掉了。...这样debug版本中有利于程序员排查问题, Release 版本不影响用户使用时程序效率。...b值,不过x地址和a地址⼀样,y地址和b地址⼀样,相当于x和y是独⽴空间,那么Swap1函数内部交换x和y值,⾃然不会影响a和b,当Swap1函数调⽤结束后回到main函数,a和b没法交换...Swap1函数使⽤时候,是把变量本⾝直接传递给函数,这种调⽤函数⽅式我们之前函数时候就知道了,这种叫值调⽤。...所以未来函数只是需要主调函数变量值来实现计算,就可以采用值调用。如果函数内部要修改主调函数变量值,就需要址调用。

8910

Linux:进程控制(二.详细讲解进程程序替换)

因此,虽然我们常说是“程序替换”,但实际上更准确地说是将新程序加载到内存,替换掉原有的程序,以实现进程功能切换和更新。 程序运行要加载到内存;为什么?冯诺依曼体系规定;如何加载呢?...它原型如下: int execle(const char *path, const char *arg, ..., char *const envp[]); path 是要执行可执行文件路径,arg...进程程序替换不会替换环境变量 想要子进程继承全部环境变量,不用管,直接就能拿到 单纯新增环境变量,父进程里使用putenv()函数,会影响子进程 putenv 是 C 语言中一个库函数...,它定义 头文件。...int putenv(const char *string); 使用全新环境变量,就使用execle()函数,那么替换后代码切换后环境变量就只是我们传入表里内容 也可以调用其他语言程序 code.c

14110

C语言:字符函数和字符串函数

0; } 二、字符转换函数 C语⾔提供了2个字符转换函数: int tolower ( int c ); //将参数进去⼤写字⺟转⼩写 int toupper ( int c ); //将参数进去...char * str ); 3.1 使用注意事项 1、字符串以 '\0' 作为结束标志,strlen函数返回字符串 '\0' 前⾯出现字符个数(包含 '\0' )。...-*str2; } 十、strstr使用和模拟实现 char * strstr ( const char * str1, const char * str2); 10.1 使用注意事项 1、函数返回字符串...str2字符串str1第⼀次出现位置 2、字符串⽐较匹配包含 \0 字符,以 \0 作为结束标志 10.2 strstr模拟实现 char* my_strstr(const char* str1...strerror函数需要使用error.h头文件,因为是erron这个变量,他比较粗暴,是暂时将该错误信息存储起来,我们可以把它写进文件里,也可以先记录但是暂时不打印,比较灵活。

9710

C++11】万能引用与完美转发

模板&&—万能引用 首先我们来看这样一段代码: 这里有4个函数,我们很容易能看出来它们是一个重载关系 然后我们给这样一个函数模板 大家看这个函数模板参数,T&& t 这里有两个...模板&&代表右值引用,而是万能引用,其既能接收左值又能接收右值。 我们实例化这个函数模板时候 可以左值,也可以右值。...为什么全部匹配都是左值引用啊! 那这里为什么会这样呢?...第一次传递给push_back 参数,右值的话就调用右值引用版本push_back ,但是push_back里面调用insert第二次传递,就变成左值了 所以最终不论是右值还是左值push_back...ch) { string tmp(*this); tmp += ch; return tmp; } const char* c_str() const { return

10210

指针(1)--对于指针基本概念介绍

指针是我们学习C语言中绕不开一个话题。那么指针究竟是什么?为什么它如此重要?它用法有哪一些呢?接下来进行指针详解。 注:接下来针对指针讲解都基于C语言展开以便于更好理解。...同理,64位计算机中就是8个字节。 所以我们可以得知,指针变量大小取决于地址大小而取决于类型。无论是int、char等等,指针变量大小都是一个地址大小。...(2)值调用 设想:通过调用函数来打印值 值调用函数参数值被复制到函数形参。这意味着函数内部对形参修改不会影响到实参值。...如果我们需要解决这个问题,就需要用到址调用。 结果就是: 址调用函数参数地址被传递给函数形参。这意味着函数内部对形参修改会影响到实参值。...传递给函数是实参地址,函数内部对形参修改会影响到实参。

3810

C++:01---函数重载、缺省参数

) 作用域必须相同 函数重载与函数返回值无关 哪些情况构成重载、构成重载 ①顶层const构成重载,所以下面的两个函数构成重载 int add(int a,int b); int add(const...常量引用或者常用指针构成重载,所以下面两组函数都构成重载(因为const对象不能转换为其它类型,所以只能将const对象传递给const形参。...下面的代码规范(不应该在一个函数声明一个函数)。...但是不能用函数局部变量初始化 int a=10; int b=20; char c='a'; void func(int num1=a,int num2=b,char s=c); 注意事项...,main函数调用到某函数时,跳到栈对应函数位置,并返回结果 普通函数调用与内联函数内存模型 ?

90720

c语言从入门到实战——初识指针

Swap1函数使用时候,是把变量本身直接传递给函数,这种调用函数方式我们之前函数时候就知道了,这种叫值调用。...那么就可以使用指针了,main函数中将a和b地址传递给Swap函数,Swap函数里边通过地址间接操作main函数a和b,并达到交换效果就好了。...,顺利完成了任务,这里调用Swap2函数时候是将变量地址传递给函数,这种函数调用方式叫:址调用。...址调用,可以让函数和主调函数之间建立真正联系,函数内部可以修改主调函数变量;所以未来函数只是需要主调函数变量值来实现计算,就可以采用值调用。...如果函数内部要修改主调函数变量值,就需要址调用。

9010

C语言指针详解

空指针  指向空,或者说指向任何东西。C语言中,我们让指针变量赋值为NULL表示一个空指针,而C语言中,NULL实质是 ((void*)0) ,  C++,NULL实质是0。  ...当把数组名赋值给一个指针后,再对指针使用sizeof运算符,返回是指针大小。  这就是为什么我么将一个数组传递给一个函数时,需要另外用一个参数传递数组元素个数原因了。  ... 函数参数和指针  C语言中,实参传递给形参,是按值传递,也就是说,函数形参是实参拷贝份,形参和实参只是值上面一样,而不是同一个内存数据对象。...这就意味着:这种数据传递是单向,即从调用者传递给被调函数,而被调函数无法修改传递参数达到回效果。  ...,简单情况下是可以,但是如果返回值有其它用途(例如返回函数执行状态量),或者要回数据不止一个,返回值就解决不了了。

2.1K20

C语言】回调函数

一、回调函数定义 回调函数就是一个通过函数指针调用函数。如果你把函数指针(地址)作为参数传递给另一个 函数,当这个指针被用来调用其所指向函数时,我们就说这是回调函数。...int compare(const void* p1,const void* p2) { return *(int*)p1 - * (int*)p2; //强制转换为int*再解引用;需要用什么类型比较就强转为什么类型...sizeof计算 qsort(s, sz, sizeof(s[0]), compare); Print(s,sz); return 0; } 以上两种类型排序,compare...函数都是回调函数; 三、利用冒泡排序思想模拟实现qsort()函数 这个bubble_sort函数可以排序任意类型数据 两个核心函数: 交换函数,这里分别是两个元素地址和每个元素类型大小...是首元素地址,+j是访问它下一个元素,但不知道使用者创建compare函数传入首地址是什么类型,所以用void接收,所以这里我们将它强制转换为char类型,因为char指针+1跳过一个字节,使base

12110

C++11特性大杂烩

若要深层次去了解,可以去C++官方库查询学习:point_right:C++11官方库语法统一列表初始化:{}初始化C++98,标准允许使用花括号{}对数组或者结构体元素进行统一列表初始值设定。...(x);//move之后左值可以右值引用那好端端有了引用(左值引用),为什么还要在C++11提出右值引用呢?...,移动构造和移动赋值作用是通过移动右值资源,减少了拷贝构造次数,减少了损耗万能引用和完美转发万能引用首先需要模板,然后参数列表是模板参数 &&图片模板&&代表右值引用,而是万能引用也称折叠引用...,也可以被修改,所以函数PerfectForward后续使用右值会被识别成左值。...这个数组纯粹是通过构造数组同时展开参数包图片在C++11容器里函数也有拓展到能使用到可变模板参数,这类函数称为empalce系列函数STL容器empalce相关接口函数list和vector里面都提供有

87850

C 语言指针最详尽讲解

由于内存每一个字节都有一个唯一编号。 因此,程序中使用变量,常量,甚至数函数等数据,当他们被载入到内存后,都有自己唯一一个编号,这个编号就是这个数据地址。 指针就是这样形成。...空指针 指向空,或者说指向任何东西。 C语言中,我们让指针变量赋值为NULL表示一个空指针,而C语言中,NULL实质是 ((void*)0) , C++,NULL实质是0。...当把数组名赋值给一个指针后,再对指针使用sizeof运算符,返回是指针大小。 这就是为什么将一个数组传递给一个函数时,需要另外用一个参数传递数组元素个数原因了。...函数参数和指针 C语言中,实参传递给形参,是按值传递,也就是说,函数形参是实参拷贝份,形参和实参只是值上面一样,而不是同一个内存数据对象。...这就意味着:这种数据传递是单向,即从调用者传递给被调函数,而被调函数无法修改传递参数达到回效果。

84840

C语言指针做函数参数,指针做函数返回类型

有时候我们可以使用函数返回值来回数据,简单情况下是可以,但是如果返回值有其它用途(例如返回函数执行状态量),或者要回数据不止一个,返回值就解决不了了,所以要引用上指针来传递。...指针做函数参数: C语言中,函数参数不仅可以是整数、小数、字符等具体数据,还可以是指向它们指针。...这就意味着,两种形式都不能将数组所有元素“一股脑”传递进来,大家还得规规矩矩使用数组指针。*/ //真正传递数组可以有少于或多于 100 个元素。...b); C语言为什么不允许直接传递数组所有元素,而必须传递数组指针呢?...,函数运行结束后会销毁在它内部定义所有局部数据,包括局部变量、局部数组和形式参数,函数返回指针请尽量不要指向这些数据,C语言没有任何机制来保证这些数据会一直有效,它们在后续使用过程可能会引发运行时错误

2.5K20

sqlite3_exec函数使用

sqlite3_exec函数使用 sqlite3数据库是一个小型关系型数据库,以文件方式存在,打开文件即是打开数据库,它小巧且功能强大,嵌入式领域内使用很广.现在就介绍一下其中一个重要函数使用...,程序注释比较详细,很容易看懂,我就不多说了.程序执行前提是我本目录下有一个提前创建好有两个数据条目的名字叫environment数据表在数据库文件db.db ?...int f_num 查找到记录包含字段数目 char **f_value 包含查找到每个记录字段值 char **f_name 包含查找到每个记录字段名称 * 返 回 值:成功返回0...现在看看给回调函数参: /************************************************** * 文件名称:main.c * 文件描述:测试sqlite3sqlite3...int f_num 查找到记录包含字段数目 char **f_value 包含查找到每个记录字段值 char **f_name 包含查找到每个记录字段名称 * 返 回 值:成功返回0

3K10

C++: 06---构造函数析构函数

深拷贝不但对指针进行拷贝,而且对指针指向内容进行拷贝,经深拷贝后指针是指向两个不同地址指针。 如图: ? 思考: 当对象存在指针成员时,为什么需要自己实现拷贝构造函数?...如果,会出现怎样问题?...也不能用*,若写成 CGoods(const CGoods* rhs),就会变成一个构造函数,CGoods*是已存在对象地址。...如果是自赋值,那么p和被拷贝指针是同一指针,赋值操作前对pdelete操作,将导致p所指数据同时被销毁。 拷贝构造函数与赋值函数区别?     ...String类声明函数: 1、构造函数 /*    1、构造函数构造对象时使用;   2、传入参数判断;   3、对象初始化问题。

64720

C++与Cconst关键字有何差别?

前言 const关键字到底该怎么用》一文中介绍了C语言中const关键字,本文说说C++const关键字,它大部分特点和C语言中类似,所以本文主要针对不同之处。...但是,千万不要写这样代码!!! 与C语言中const关键字不同是,C++中使用const关键字定义b变量值在被改变时会被检测。...因为前者传递指针副本,指针指向不会被改变,但可以改变指向内容;但是int类型参数,它也是传递副本,但是永远不会被函数改变,自然也没有必要加const关键字。更多解释可以参考《值和指针》。...即下面的声明是非法: static void printA() const 修饰类成员变量--构造函数初始化 与修饰普通变量不同是,修饰类成员变量还可以构造函数初始化。...总结 关于const关键字CC++区别,想必到这里你已经清楚了。const关键字通常能借助编译器帮助我们提前发现一些不易察觉问题。

68000

Effective Modern C++翻译(2)-条款1:明白模板类型推导

想要在现代C++中进行有效率编程,你必须对类型推导操作有一个扎实了解,因为有太多情形你会用到它,函数模板调用auto出现大多数场景decltype表达式C++14,神秘decltype...通过这种方式,C++模板类型推导成为了一个巨大成功,数百万程序员向模板函数传递参数,并获得完全令人满意答案,尽管很多程序员被紧紧逼着去付出比对这些函数是如何被推导一个朦胧描述要更多。...用一个int类型调用函数f T被推导为int,但是ParamType被推导为const int& 我们很自然去期待推导出T类型和传递给函数实参类型是一致,例如,T类型就是expr类型,在上面的例子...但是如果数组通过方式传递给一个模板时候,会发生什么呢?...因为数组参数声明被按照指针声明而对待,通过按值方式传递给一个模板参数数组将被推导为一个指针类型,这意味着在下面这个模板函数f调用,参数T类型被推导为const char* f(name);

762100
领券