详解C语言中sizeof如何在自定义函数中正常工作

1、在main函数中,sizeof是可以正常工作的,比如:

int main()
{
	int n[5];
	printf("input: \n");
	int i ;
	for(i = 0; i < 5; i++)
	{
		scanf("%d",n + i);
	}
	int len = sizeof(n)/sizeof(n[0]);
	printf("%d\n",len);
	return 0;
}

2、但是在自定义函数中就不可以了,如下:

#include <stdio.h>
void print_1(int n[])
{
	int i;
	int len = sizeof(n)/sizeof(n[0]);
	printf("len : %d\n",len);
	for(i  = 0; i < len; i++)
	{
		printf("%d",n[i]);
	}

	printf("\n");
}
int main()
{
	int n[5];
	printf("input: \n");
	int i ;
	for(i = 0; i < 5; i++)
	{
		scanf("%d",n + i);
	}

	print_1(n);
	printf("\n");
	return 0;
}

3、至于原因以及解决方法感觉有篇博客说的比较好

原因在于:第一,在c中,数组在作为参数的时候就退化为指针,对一个地址来取大小呢,如果是32位系统的话即为4,如果是64位系统的话为8,所以呢,在函数中sizeof获取的是指针的长度而不是数组的长度。第二呢,在函数中,sizeof的处理时间的在编译期,也就是说对于动态生成的数组大小是不能用sizeof来算出来的。

4、解决办法

第一种办法

把数组作为参数传入到数组的同时呢,也传入该数组的长度进去。不过该办法需要在函数外获取该数组的长度才传进去,略显麻烦。比如讲上述代码的打印函数的函数名print(int *n) ; 改成print(int *n ,int len);其中len代表数组n的长度

第二种办法

采用宏定义,但是这种方法个人感觉显得有些啰嗦

第三种办法

C++可以用vector等容器避免大部分数组的操作,对于字符数组也有string可以替代,也有可以传递数组大小的奇迹淫巧。如果你需要计算数组长度的函数,可以使用宏定义 或者 如果是C++,也用相应的模板技巧,这比宏定义安全。

template <size_t N>
long calc(long (&array)[N]) // 利用模板传递参数 array是数组的引用
{
    long res = 0L;

    for (size_t i = 0;i < N;i ++) {
        res += array[i];
    }

    return res;
}

int main()
{
    long longarr[] = {1, 23, 4, 45, 46, 57,};

    long sum = calc(longarr);
}

总结:在写这些小的程序时,若没有特殊要求,直接将数组的长度确定,就不需要这么麻烦了

到此这篇关于详解C语言中sizeof如何在自定义函数中正常工作的文章就介绍到这了,更多相关C语言sizeof内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • C语言中sizeof函数踩过的坑总结

    sizeof很简单,但是却很容易令人踩坑. 正文 先来看这样一段代码 int main() { int i=2; printf("%d\n",sizeof(i++)); printf("%d\n",i); return 0; } 非常简单的一段代码 当时我认为答案应该是 4 3 可是结果却是出乎我的意料了 这是为什么呢? 下面来仔细说一下 通过调试观察虽然确实有i++这么一句代码,但是却没有实现.说到这里很多人可能犯了和我一样的错误,认为sizeof是一个函数. 其

  • C语言中sizeof函数的基本使用总结

    前言 C语言中的sizeof是一个很有意思的关键字,经常有人用不对,搞不清不是什么.我以前也有用错的时候,现在写一写,也算是提醒一下自己吧. sizeof是什么 sizeof是C语言的一种单目操作符,如C语言的其他操作符++.--等,sizeof操作符以字节形式给出了其操作数的存储大小.操作数可以是一个表达式或括在括号内的类型名.这个操作数不好理解对吧?后面慢慢看就明白了.sizeof的返回值是size_t,在64位机器下,被定义为long unsigned int. sizeof函数的结果:

  • 对C语言中sizeof细节的三点分析介绍

    1.sizeof是运算符,跟加减乘除的性质其实是一样的,在编译的时候进行执行,而不是在运行时才执行.那么如果编程中验证这一点呢?ps:这是前两天朋友淘宝面试的一道题,小编理解: 复制代码 代码如下: #include<iostream> using namespace std; int main() {     int i=1;     cout<<i<<endl;     sizeof(++i);     cout<<i<<endl;    

  • C语言 sizeof 函数详情

    目录 一.sizeof 函数简介 二.sizeof 函数实战 一.sizeof 函数简介 在 C 语言中,char 字符串也是一种非常重要的数据类型,我们除了使用 sizeof 函数获取字符串长度之外,使用 sizeof 函数同样也可以完成字符串长度的获取: 字符串:一般用一对双引号" "括起的一串字符来表示字符串常量,字符串默认以转义字符'\0'结尾,字符串常量是不可被修改的: sizeof 函数会扫描整个字符串,直到碰到第一个字符串结束符 '\0'为止,然后返回计数器值(长度包含'

  • 浅析C语言中的sizeof

    这是一个依赖于编译系统的值,一般定义为typedef unsigned int size_t;编译器林林总总,但作为一个规范,都会保证char.signedchar和unsigned char的sizeof值为1,毕竟char是编程能用的最小数据类型.MSDN上的解释为:The sizeof keyword gives the amount of storage, in bytes, associated with avariable or atype (including aggregate

  • 详解C语言中sizeof如何在自定义函数中正常工作

    1.在main函数中,sizeof是可以正常工作的,比如: int main() { int n[5]; printf("input: \n"); int i ; for(i = 0; i < 5; i++) { scanf("%d",n + i); } int len = sizeof(n)/sizeof(n[0]); printf("%d\n",len); return 0; } 2.但是在自定义函数中就不可以了,如下: #includ

  • 举例详解Go语言中os库的常用函数用法

    (f *File).Name()这个函数是返回文件的名称,函数原型func (f *File) Name() string要文件的指针操作,返回字符串,感觉比较鸡助的方法底层实现 复制代码 代码如下: func (f *File) Name() string { return f.name }  import (  "fmt"  "os" ) func main() {  f, _ := os.Open("1.go")  fmt.Println(

  • 详解C++语言中std::array的神奇用法

    概述 std::array是在C++11标准中增加的STL容器,它的设计目的是提供与原生数组类似的功能与性能.也正因此,使得std::array有很多与其他容器不同的特殊之处,比如:std::array的元素是直接存放在实例内部,而不是在堆上分配空间:std::array的大小必须在编译期确定:std::array的构造函数.析构函数和赋值操作符都是编译器隐式声明的--这让很多用惯了std::vector这类容器的程序员不习惯,觉得std::array不好用.但实际上,std::array的威力

  • 详解C语言中return与exit的区别

    详解C语言中return与exit的区别 1,exit用于在程序运行的过程中随时结束程序,exit的参数是返回给OS的.main函数结束时也会隐式地调用exit函数.exit函数运行时首先会执行由atexit()函数登记的函数,然后会做一些自身的清理工作,同时刷新所有输出流.关闭所有打开的流并且关闭通过标准I/O函数tmpfile()创建的临时文件.exit是结束一个进程,它将删除进程使用的内存空间,同时把错误信息返回父进程,而return是返回函数值并退出函数 2,return是语言级别的,它

  • 详解 Go 语言中 Map 类型和 Slice 类型的传递

    Map 类型 先看例子 m1: func main() { m := make(map[int]int) mdMap(m) fmt.Println(m) } func mdMap(m map[int]int) { m[1] = 100 m[2] = 200 } 结果是 map[2:200 1:100] 我们再修改如下 m2: func main() { var m map[int]int mdMap(m) fmt.Println(m) } func mdMap(m map[int]int) {

  • 详解C语言中Char型指针数组与字符数组的区别

    详解C语言中Char型指针数组与字符数组的区别 1.char 类型的指针数组:每个元素都指向一个字符串,指向可以改变 char *name[3] = { "abc", "def", "gbk" }; for(int i = 0 ; i < strlen(name); i ++){ printf("%s\n", *(name+i)); //printf("%s\n", name[i]); } //指向改

  • 详解Go语言中for range的"坑"

    前言 Go 中的for range组合可以和方便的实现对一个数组或切片进行遍历,但是在某些情况下使用for range时很可能就会被"坑",下面用一段代码来模拟下: func main() { arr1 := []int{1, 2, 3} arr2 := make([]*int, len(arr1)) for i, v := range arr1 { arr2[i] = &v } for _, v := range arr2 { fmt.Println(*v) } } 代码解析

  • 详解Golang语言中的interface

    interface是一组method签名的组合,interface可以被任意对象实现,一个对象也可以实现多个interface.任意类型都实现了空interface(也就是包含0个method的interface),空interface可以存储任意类型的值.interface定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口. go version go1.12 package main import ( "fmt" ) // 定义struct type Hu

  • 详解go语言中type关键词的几种使用

    type是go语法里的重要而且常用的关键字,type绝不只是对应于C/C++中的typedef.搞清楚type的使用,就容易理解go语言中的核心概念struct.interface.函数等的使用.以下我用例子代码总结描述,请特别留意代码中的注释. 1.定义结构体 //结构体定义 type person struct { name string //注意后面不能有逗号 age int } func main() { //结构体初始化 p := person{ name: "taozs",

  • 详解R语言中的PCA分析与可视化

    1. 常用术语 (1)标准化(Scale) 如果不对数据进行scale处理,本身数值大的基因对主成分的贡献会大.如果关注的是变量的相对大小对样品分类的贡献,则应SCALE,以防数值高的变量导入的大方差引入的偏见.但是定标(scale)可能会有一些负面效果,因为定标后变量之间的权重就是变得相同.如果我们的变量中有噪音的话,我们就在无形中把噪音和信息的权重变得相同,但PCA本身无法区分信号和噪音.在这样的情形下,我们就不必做定标. (2)特征值 (eigen value) 特征值与特征向量均为矩阵分

随机推荐