wq_601840968 发表于 2019-1-17 10:51:38

关于C结构体指针初始化语法的疑问?

本帖最后由 wq_601840968 于 2019-1-17 10:52 编辑

如下图:


标号处语法不太明白。

takashiki 发表于 2019-1-17 10:59:36

今年2019年了,C99标准到现在已经20年了,有空还是看一下吧。最好C11标准也看下,万一啥时用到了呢。

RAMILE 发表于 2019-1-17 11:04:57

现在的keil 能在函数中间定义局部变量吗?

wq_601840968 发表于 2019-1-17 11:13:20

takashiki 发表于 2019-1-17 10:59
今年2019年了,C99标准到现在已经20年了,有空还是看一下吧。最好C11标准也看下,万一啥时用到了呢。 ...

匿名结构体?

tragedy 发表于 2019-1-17 11:15:24

看这里 常规操作
http://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Designated-Inits.html

takashiki 发表于 2019-1-17 11:17:52

wq_601840968 发表于 2019-1-17 11:13
匿名结构体?

1、结构体指定初始化
2、复合字面量
这两项你都看一下,你就明白了。这个不是匿名的,他不是有名字嘛。

takashiki 发表于 2019-1-17 11:24:08

RAMILE 发表于 2019-1-17 11:04
现在的keil 能在函数中间定义局部变量吗?

MDK可以。加上gnu或c99编译选项或者干脆上C++。
C51似乎连C89都没有完全遵守,估计是不行的,不过可以用{}括起来,局部变量只要位于{}块语句开头就可以了,switch语句除外。

wq_601840968 发表于 2019-1-17 11:38:40

takashiki 发表于 2019-1-17 11:17
1、结构体指定初始化
2、复合字面量
这两项你都看一下,你就明白了。这个不是匿名的,他不是有名字嘛。 ...

soga,复合字面量 {:handshake:}

laoshuhunya 发表于 2019-1-17 13:37:57

ISO/IEC 9899:2018 都出来了,国内售价¥1388

tomzbj 发表于 2019-1-17 16:17:30

本帖最后由 tomzbj 于 2019-1-17 16:18 编辑

感觉有点多此一举
如果是初始化结构体, 直接foo_t t={1,2}就可以;
如果在程序中间赋值, 可以t = (foo_t){1,2};
匿名结构体也可以作为函数参数.
以下程序用gcc -Wall编译正常运行, 无warning.

#include <stdio.h>

typedef struct {
    int a;
    float b;
} test_t;

void func(test_t* t)
{
    printf("%d %f\n", t->a, t->b);
}

int main(void)
{
    test_t t1 = {2, 3.0};          // 正常初始化
    func(&t1);

    test_t t2;
    t2 = (test_t) {7, 5.0};      // 需要强制类型转换
    func(&t2);
    func(&(test_t){1, 2.0});      // 匿名结构体作为函数参数
    return 0;
}

Jmhh247 发表于 2019-1-17 17:09:47

tomzbj 发表于 2019-1-17 16:17
感觉有点多此一举
如果是初始化结构体, 直接foo_t t={1,2}就可以;
如果在程序中间赋值, 可以t = (foo_t){1, ...

当然不是多此一举。

如果用别人的库,别人改动了结构体成员位置,比如

typedef struct {
    int a;
    float b;
} test_t;改成了

typedef struct {
    float b;
    int a;
} test_t;

指定变量去初始化,怎么改都不怕。。。


RAMILE 发表于 2019-1-17 20:02:25

tomzbj 发表于 2019-1-17 16:17
感觉有点多此一举
如果是初始化结构体, 直接foo_t t={1,2}就可以;
如果在程序中间赋值, 可以t = (foo_t){1, ...

test_t t1 = {2, 3.0};          // 正常初始化

这是书上严厉打击的赋值方法,如果有人修改结构体,出一堆bug

flash3g 发表于 2019-1-17 20:47:19

RAMILE 发表于 2019-1-17 20:02
test_t t1 = {2, 3.0};          // 正常初始化

这是书上严厉打击的赋值方法,如果有人修改结构体,出一 ...

一般都是 用“.”或者“->” 赋值

t3486784401 发表于 2019-1-17 21:21:08

这个语法在 VS8.0 (2005)下直接不通过,不知其他版本的 VS 是否也是这个特性。

相应的,VS 一般使用构造函数(结构体也有)来初始化结构体,连初始赋值都少用了。

t3486784401 发表于 2019-1-17 21:22:18

tomzbj 发表于 2019-1-17 16:17
感觉有点多此一举
如果是初始化结构体, 直接foo_t t={1,2}就可以;
如果在程序中间赋值, 可以t = (foo_t){1, ...

VS8.0 下 C++ 环境,第 19、21 行直接报错,看来 VS 环境检查的也挺严

nanfang2000 发表于 2019-1-17 21:32:33

t3486784401 发表于 2019-1-17 21:22
VS8.0 下 C++ 环境,第 19、21 行直接报错,看来 VS 环境检查的也挺严

这不是严格而是一直vs不支持c99。新的vs好像才支持

takashiki 发表于 2019-1-17 21:34:40

t3486784401 发表于 2019-1-17 21:21
这个语法在 VS8.0 (2005)下直接不通过,不知其他版本的 VS 是否也是这个特性。

相应的,VS 一般使用构造 ...

他这个是C,你用C++去编译,报错很正常好吧。
C++和C是两种完全不一样的语言,C++从来就没有100%兼容过C语言,凡是到处鼓吹C++完全兼容C的,都是骗人的:就算是C89,C++也不完全兼容。从C99开始,不兼容进一步扩大;到C11时,基本上就是儿童相见不相识笑问客从何处来了。
C99好多特性都是从GCC演化而来,所以GCC的C++可能会兼容,但是VS的C++可以根本不鸟,本来就不是标准。

t3486784401 发表于 2019-1-17 23:20:12

nanfang2000 发表于 2019-1-17 21:32
这不是严格而是一直vs不支持c99。新的vs好像才支持

看了看,的确 VS 对于 C99 的支持一般般

t3486784401 发表于 2019-1-17 23:21:09

takashiki 发表于 2019-1-17 21:34
他这个是C,你用C++去编译,报错很正常好吧。
C++和C是两种完全不一样的语言,C++从来就没有100%兼容过C ...

受教了,看样子都是神仙打架

t3486784401 发表于 2019-1-17 23:42:20

takashiki 发表于 2019-1-17 21:34
他这个是C,你用C++去编译,报错很正常好吧。
C++和C是两种完全不一样的语言,C++从来就没有100%兼容过C ...

手头单片机的 C 编译器都不行,目前可以通过的只有 Arduino (G++)

不过 G++ 这个只能支持结构体顺序初始化,乱序的初始化也是不支持。

takashiki 发表于 2019-1-18 05:56:04

t3486784401 发表于 2019-1-17 23:42
手头单片机的 C 编译器都不行,目前可以通过的只有 Arduino (G++)

不过 G++ 这个只能支持结构体顺序初 ...

底层是GCC或支持GCC扩展的都可以,比如WinAVR、ARM GCC、Keil MDK加上--gnu控制。
支持C99的单片机编译器也不少了,IAR for ARM、Keil MDK,不过默认都是C89的,需要在选项中开启。
支持C11的编译器是真没见过,网上的信息也不多,还有很多挂羊头卖狗肉的,标题写C11,内容写C++11的。

hyf88 发表于 2019-2-4 18:03:23

tragedy 发表于 2019-1-17 11:15
看这里 常规操作
http://gcc.gnu.org/onlinedocs/gcc-3.4.5/gcc/Designated-Inits.html

为什么推荐 gcc 3.4.5 版本的文档呢?最新的是gcc 8了,
页: [1]
查看完整版本: 关于C结构体指针初始化语法的疑问?