游戏开发论坛

 找回密码
 立即注册
搜索
12
返回列表 发新帖
楼主: lv5329545

关于函数指针和共用体的问题

[复制链接]

1

主题

50

帖子

52

积分

注册会员

Rank: 2

积分
52
发表于 2008-4-30 19:24:00 | 显示全部楼层

Re: Re:关于函数指针和共用体的问题

funcman: Re:关于函数指针和共用体的问题

考虑到和C语言的兼容,const char*是可以赋值给char*的。所以上面那位同学的理解和实际情况还是有些偏差的。
LZ在字符指针指向字符串常量的操作上没什么问题。

const char *cstr = "1234";
char *str = cstr ;        
//error C2440: “初始化”: 无法从“const char*”  转换为“char*"
//这里可以编译通过的话 你就可以直接修改const常量了
//char *str = (char *)cstr; 这样的话编译器为你产生匿名变量(明确说是字符数组,下同),,编译通过

为什么初始化和参数赋值可以通过?
void print(char *str){}
print("123");   
//编译通过
//其实这里会产生临时变量,str指向的是编译器生成的匿名变量

初始化操作也是同样的道理..
struct STRING
{
        char *m_name;
};

STRING strings[] = {"1234", "5678"};
编译器都会产生临时变量,你指向其实是编译器的匿名变量

楼主的字符串初始化的确没问题,结构中的char *指针会指向编译器为你生成匿名
变量,并储存在公共变量区


备注:早期c\c++编译器可能无法通过编译,因为这样会隐式产生匿名变量,不过这样
可以方便好多.
const char cstr[] = "1234";可以看成 const char cstr[] = {'1','2','3','4'};
但是 const char *cstr[] = "1234"; 和  const char *cstr = {'1','2','3','4'}; 后者会编译错误,这里可以看出const char* cstr = "1234"的特殊性.
其实编译器先会生成一个匿名字符数组存放"1234",然后把这个数组的地址赋值给cstr.



86

主题

2251

帖子

2386

积分

金牌会员

Rank: 6Rank: 6

积分
2386
QQ
发表于 2008-5-1 16:50:00 | 显示全部楼层

Re:关于函数指针和共用体的问题

哈,我说“考虑到和C语言的兼容,const char*是可以赋值给char*的。”是不对的,说“考虑到和C语言的兼容,“有时候”const char*是可以赋值给char*的。”才准确些。

01  #include <stdio.h>$
02  int main() {
03      char* str = "Hello";
04      str[1] = 'a';
05      return 0;
06  }

在任何符合标准的C++编译器都能通过编译。但Linux上执行由GCC编译的执行文件会“段错误”,Win32上有可能顺利执行(看编译器和编译器出的版本是Debug还是Release,具体记不得了)。主要是看系统有没有对字符串常量所在段进行保护。

如果没有C存在的话,上面程序的03行应该报错才对。字符串常量作为右值时,最好做法是作为const char*类型。考虑兼容性,没有这么做,从而带来了很多问题。C89标准太顽强,不好让C和新特性兼容。

“转型const到nonconst会带来额外内存的开销,所以编译器不会隐式转型”这句显然是不正确的。

01  #include <stdio.h>
02  int main() {
03      const char* str = "Hello";
04      char* s = (char*)str;
05      s[1] = 'a';
06      return 0;
07  }

如果这么强制转一下,编译器就生产一个临时字符数组,那么应该不会导致运行时错误。但实际上在Linux上还是“段错误”了。说明,这只是才语法层面上破除了const的保护。

你写到:
char func_name1[] = "print1";
char func_name2[] = "print2";
func_type func_table[] = {
   { func_name1, print1},     //char []类型这里会被编译器转换为 char *
   { func_name2, print2}      //char []类型这里会被编译器转换为 char *
};

显然这有错了,因为char func_name1[] = "print1";,所以"print1"是一个局部字符数组,在栈中,它是有生命周期的。LZ原来代码的结构体中的字符指针指向了静态区中存储的字符串常量,它的生命周期是全局的,可能受到保护机制的保护,只要不改就没事。而你的代码,只要出了作用域,铁定崩溃。

还有临时变量的概念,你也理解得不对。void func(char*);这样的,进函数体时生产一个临时指针而已。只有函数的参数有对象时,函数体内的临时变量才稍微复杂化一点。临时变量的复杂,主要是在对象的操作上体现。字符串常量和对象还是两种东西。由于和C兼容,C++的字符串常量不是一个常量字符串对象。

86

主题

2251

帖子

2386

积分

金牌会员

Rank: 6Rank: 6

积分
2386
QQ
发表于 2008-5-1 17:07:00 | 显示全部楼层

Re: Re: Re:关于函数指针和共用体的问题

#include <stdio.h>
int main() {
    int i = "Hello";
    return 0;
}

gcc编译报错:“ 错误: 从类型 ‘const char*’ 到类型 ‘int’ 的转换无效”

可见字符串常量在大多数时候,作为右值时就是个“const char*”。但字符串常量作为右值赋给一个char*时,就是不报错。

这就是我说的为了兼容C。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2026-1-22 16:18

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表