V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
Newyorkcity
V2EX  ›  问与答

C 语言指针,请问我这个代码到底为啥报错? Invalid type argument of unary '*' (have int)

  •  
  •   Newyorkcity · 2017-02-10 17:13:04 +08:00 · 7364 次点击
    这是一个创建于 2843 天前的主题,其中的信息可能已经有所发展或是发生改变。

    main.c

    #include <stdio.h>
    #include <stdlib.h>
    #include "declaration.h"
    
    /* run this program using the console pauser or add your own getch, system("pause") or input loop */
    
    int main(int argc, char *argv[]) {
    	int *num = array_create(5);
    	int number;
    	int index = 0;
    	
    	do{
    		scanf("%d",&number);
    		*(array_at(num, index ++)) = number; //编译器认为这里错误, array_at 函数代码在下方
    	} while(number != -1);
    	
    	printf("num = %s",num);
    	array_free(num);
    	return 0;
    }
    

    array.c

    int *arrary_at(int num[], int index){
    	// 用户输入要数组第几个单元,并且可以输出、修改这个值
    	
    	//如果给出单元已经越界,则应该扩展数组
    	int n = sizeof(num)/sizeof(int)-1; 
    	if (index >= n){
    		num = arrary_inflate(num);
    	}
    
    	return &(num[index]); 
    }
    

    求解,谢谢!~
    24 条回复    2017-02-11 19:50:55 +08:00
    tsunli
        1
    tsunli  
       2017-02-10 17:20:14 +08:00
    int *num = array_create(5);
    -- 这里申明的 num 是指针.

    int *arrary_at(int num[], int index){
    --这里申明的 num 是数组。

    num 类型不一致.
    Newyorkcity
        2
    Newyorkcity  
    OP
       2017-02-10 17:26:34 +08:00
    @tsunli 不是说数组是一种特殊的指针类型么?另外我把所有出现 num[]的地方都给改成了*num ,可是还是报一样的错误。能麻烦你再看看么?谢谢
    aheadlead
        3
    aheadlead  
       2017-02-10 17:28:29 +08:00
    arrary_at 这个函数是不是打错名字了?
    aheadlead
        4
    aheadlead  
       2017-02-10 17:30:42 +08:00   ❤️ 1
    @Newyorkcity
    数组是一个地址的常量;
    指针类型的变量里面存放的也是地址。

    直接说数组就是指针不恰当。
    xss
        5
    xss  
       2017-02-10 17:34:53 +08:00
    你的 array_at 函数的第一个参数类型是 int []
    你竟然传给他一个 int *的实参
    编译器当然不让你过了.
    Newyorkcity
        6
    Newyorkcity  
    OP
       2017-02-10 17:36:20 +08:00
    @aheadlead 谢谢,确实是名字错误,真是。。。
    不过考虑数组和指针不同的话,应该怎么写呢?因为我这里用到了 sizeof(num)/sizeof(int)来获得数组的长度,如果不用数组而用指针的话 sizeof ( num )会把这个理解为指针变量的大小吧?
    另外好像 num[] = malloc(**)也会报错。。
    谢谢
    nbndco
        7
    nbndco  
       2017-02-10 17:42:40 +08:00 via iPhone   ❤️ 1
    @Newyorkcity 不可能,必须把长度传进去。某种意义上[]和指针是一样的,运行时都只是一个指针。另外返回写 num+index 就可以了
    Newyorkcity
        8
    Newyorkcity  
    OP
       2017-02-10 17:48:19 +08:00
    @nbndco 所以最好的方法是用上结构体,把数组指针和长度绑在一个结构里吗?谢谢
    irexy
        9
    irexy  
       2017-02-10 17:55:56 +08:00   ❤️ 1
    应该是函数名打错了,你写的 arrary_at ,多了个 r 。
    另外你的程序我感觉有几个问题:
    1.你的 array_at 函数中 sizeof(num)会返回整数型指针的大小,也就是你的 n 永远等于 0
    2.array_at 的参数中 num 不是引用传递, arrary_inflate 并不能在函数中改变 num 的地址,所以并不能扩容
    nbndco
        10
    nbndco  
       2017-02-10 17:56:11 +08:00 via iPhone
    @Newyorkcity 是,虽然事实上很少有人这么做,因为你封装的还是几乎是一个裸着的功能,和原来一样,可以参考 c++ stl 的 vector 。我觉得要用 c 就先学好数据结构和一些编译和操作系统的基础,要么就别用了。用 c++至少有 stl ,用 c 追求的就是掌控的快感,不然毫无意义。
    Newyorkcity
        11
    Newyorkcity  
    OP
       2017-02-10 17:58:32 +08:00
    @nbndco 谢谢你的建议,,我学 C 也差不多就是为了之后看用 C 语言编写的数据结构和算法书做准备。
    aheadlead
        12
    aheadlead  
       2017-02-10 18:30:16 +08:00   ❤️ 1
    @Newyorkcity (回复 6#)

    array.c 里面的这个函数声明:
    int *arrary_at(int num[], int index);

    实际上,在编译时,第一个参数 int num[] 会退化成 int *num ,
    也就是说这两个写法完全等价,编译出的代码都一样。

    所以你的代码实际上不会工作,
    sizeof(num) 将会是一个常量。

    一般的做法,是把数组 num 的长度,作为另一个参数传入函数中,如:
    int *array_at(int *num, int length, int index);

    另外,函数声明中,涉及数组下标、长度这样的参数,建议用 size_t 类型,
    不过,如果初学 C 的话,可不必深究此问题。( http://jeremybai.github.io/blog/2014/09/10/size-t



    “另外好像 num[] = malloc(**)也会报错。。
    谢谢”

    请详细描述。
    Newyorkcity
        13
    Newyorkcity  
    OP
       2017-02-10 20:02:42 +08:00
    @aheadlead
    int num[] = malloc(8);
    错题提示是:[Error] 'malloc' was not declared in this scope
    aheadlead
        14
    aheadlead  
       2017-02-10 21:12:21 +08:00
    @Newyorkcity (回复 13#)
    你要看错误提示啊。

    你没有 include 头文件 stdlib.h
    Newyorkcity
        15
    Newyorkcity  
    OP
       2017-02-10 22:13:13 +08:00
    @aheadlead 抱歉抱歉,因为之前遇到这个错误的错误的时候我是加载了 stdlib 的,然后刚刚你让我上传错误代码的时候我就重新编了一个,按照最习惯流程写了,没考虑加载 stdlib.h
    加载了之后的报错是这样的:[Error] initializer fails to determine size of 'num'
    wizardforcel
        16
    wizardforcel  
       2017-02-10 22:17:18 +08:00 via Android   ❤️ 1
    有个 bug , arrary_inflate 扩展之后的数组传不到外面,要想保存得传入 int**。
    Newyorkcity
        17
    Newyorkcity  
    OP
       2017-02-10 22:29:24 +08:00
    @wizardforcel 意思是把数组的那个 num 的地址传过去吗?谢谢
    wizardforcel
        18
    wizardforcel  
       2017-02-10 23:05:52 +08:00 via Android
    @Newyorkcity 对,其他语言在创建可扩容的数组时,一般是把动态数组放在类里面。 c 语言你可以用 struct 模拟一下。
    Newyorkcity
        19
    Newyorkcity  
    OP
       2017-02-10 23:07:48 +08:00
    @wizardforcel 谢谢!
    Newyorkcity
        20
    Newyorkcity  
    OP
       2017-02-10 23:49:03 +08:00
    @wizardforcel 如果把数组的地址当做参数写在参数表中,那么它的类型应该怎么定义呢?携程 int *pnum 里 int 应该不合适吧?
    Newyorkcity
        21
    Newyorkcity  
    OP
       2017-02-10 23:51:07 +08:00
    @wizardforcel 没仔细看就瞎问,看来是用 int **pnum 来表示访问两次得到的是一个整数型。。
    msg7086
        22
    msg7086  
       2017-02-11 04:00:59 +08:00
    数组是指针常量,指针不是数组。
    kevinzhwl
        23
    kevinzhwl  
       2017-02-11 10:29:37 +08:00 via iPhone   ❤️ 1
    再补充一个,类型上数组可以退化成指针,但指针不能变成数组
    aheadlead
        24
    aheadlead  
       2017-02-11 19:50:55 +08:00   ❤️ 1
    @Newyorkcity (回复 15#)

    我不是很懂你下面这行代码的意思:
    int num[] = malloc(8);

    我猜测你是想通过 malloc 从堆申请堆内存,
    得到描述了一个 8 个 int 类型的元素的数组的空间的地址,
    然后“赋值”给数组 num 。

    实际上,这犯了语法错误,函数 malloc 返回的是指向 void 类型的指针。
    而 int num[] = ...; 中
    编译器期待 ... 应该是诸如 {233, 234, 235} 之类的东西。

    此外, malloc(8) 分配的仅仅只是一块 8 个字节的内存。

    这里你应该写成
    int *num = (int *) malloc(8 * sizeof(int));
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2616 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 04:37 · PVG 12:37 · LAX 20:37 · JFK 23:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.