《C专家编程》:函数如何返回一个数组(九)

      这节的内容比较少也比较简单,主要是觉得用的很少,所以单独提出来加深印象。主要涉及到函数如何返回一个数组的问题。还有关于内存的分配和扩展基础知识的复习。

一、如何使用指针从函数返回一个数组。

    前几节,我们分析了怎么样把一个数组当参数传递给指针。本小节换个方向讨论数据的转化:从函数返回一个数组。
严格的说,函数无法返回一个数组。但是可以让函数返回一个指向任何数据结构的指针,当然也可以是一个指向数组的指针,记住,声明必须在使用前。一个函数声明的例子如下:
int (*function())[20];

这里function是一个函数,它返回一个指针,该指针指向的是包含20个int类型元素的数组。

返回一数组的具体实现例子如下:

#include <iostream>
#include <stdlib.h>
using namespace std;
int (*function())[20]
{
	int i=0;
	int (*p)[20];//声明一个指向20个元素的指针;
	p=(int(*)[20])calloc(20,sizeof(int));
	//或者p=(int (*)[20])malloc(sizeof(int)*20);
	if(!p)//内存不够;
	{
		cout<<"the memory is not enough!"<<endl;
		return NULL;
	}
	for(i=0;i<20;i++)
		(*p)[i]=i+5;
	return p;
}
int main()
{
	int (*result)[20];
	result=function();
	if(result)
	{
		cout<<(*result)[3]<<endl;//这样访问结果,应该输出8。
		free(result);
	}
	system("pause");
	return 0;
}

运行结果如下:


或者定义这样一个结构体:
struct pp
{
 int arr[20];
}x,y;
struct pp function()  //结构体类型,返回一个结构体对象;
{
   return y;
}
x=y;
x=functoin();
如果要访问一个元素:可以用下面的方法:
x.arr[10]=100;
注意: 千万不要返回一个指向函数的局部变量的指针。以前在 这里有详细的讲解
函数可以返回的情况有:
(1)返回一个字符串常量;
(2)返回一个静态变量;
(3)返回一个全局变量;
(4)返回一个堆空间地址;
(5)最常用的就是(4)程序员自己申请一个堆区空间保存要返回的变量,然后返回。
二、使用指针创建和使用动态数组
    在很多情况下,我们并不知道数组的长度,而是使用动态数组。绝大多数的语言都支持在运行时设置数组的长度。他们允许程序员计算需要处理的数据的个数,然后申请刚好大小的数组能容纳这些数据。
    数组是静态的,数组的长度在编译期间已经确定不变。在这个领域,C语言支持很弱。你甚至不能用下面的形式:
const int number=10;
int array[number];//编译出错,期待一个整形常量表达式。
但是这样的语句在C++中是合法的。
1、现在我们来看一下如何实现动态数组,比较简单!
它的基本思路就是使用malloc()库函数来得到一大块内存的指针。然后,像引用数组一样引用这块内存,其机理就是一个数组下标访问可以改写一个指针加上偏移量。
具体代码实现如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
	int number;
	int *arr=NULL;
	int i=0;
	printf("please input the number of your array:\n");
	scanf("%d",&number);//根据具体的个数分配动态空间。
	arr=(int *)malloc(sizeof(int)*number);
	for(i=0;i<number;i++)
		arr[i]=i+5;
	for(i=0;i<number;i++)
		printf("%d-",arr[i]);
	printf("\n");
	system("pause");
	return 0;
}

输入5,运行结果:


     动态数组对于避免预定义的限制也是非常有用的。这样既可以避免空间的浪费,也可以避免内存不够用的尴尬。方便了程序员,但是一定要记住释放申请的内存,,不然会造成内存的泄漏(leak memeory)。

2、内存的扩展realloc()函数,比较简单,不要是为了练手,可能有些冗余,复习的时候可以跳过。

代码实现如下:

#include <stdio.h>
#include <stdlib.h>
int current_element=0;
int total_element=3;
char *arr=NULL;
void add_element(char c)
{
	if(current_element==total_element-1)
	{
		total_element*=2;
		arr=(char *)realloc(arr,total_element);
		if(NULL==arr)
		{
			printf("the memory is not enough!\n");
			return ;
		}
		else
		{
			printf("realloc successfully!\n");
		}
	}
	arr[current_element++]=c;
}
int main()
{
	int number;
	int i=0;
	char *add="ky";
	char array[10]="abcdefghi";
	arr=(char *)malloc(total_element);
	while(current_element < total_element-1)
		arr[current_element++]=array[i++];
	add_element(add[0]);
	add_element(add[1]);
	printf("\n");
	i=0;
	while(i<current_element)
		printf("%c-",arr[i++]);
	printf("\n");
	free(arr);
	system("pause");
	return 0;
}
运行结果:
     在笔记(八)里面用到了一个calloc(n,sizeof(value))函数,它和malloc(size)类似,但是它有两个参数,一个是变量的大小,一个是变量的个数,返回值是n个变量value的大小空间的首地址。主要适合用于数组指针的申请内存空间。
例如:
int (*p)[5];//p指向的是一个有5个int元素的内存空间;
p=(int (*)[5])calloc(5,sizeof(int));
................................

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 我不是专业的编程专家,所以我不能给你准确的答案。但是你可以参考这个网站上的代码:http://www.codeproject.com/Articles/857252/Getting-the-CPU-serial-number-in-Cplusplus。 ### 回答2: 获取CPU序列号可以通过调用操作系统提供的接口来实现,在C语言中可以使用以下步骤来完成: 1. 包含头文件:首先需要包含相关的头文件,例如windows.h或unistd.h等,以便能够使用系统提供的函数和数据结构。 2. 定义变量:定义一个字符数组变量来存储获取到的CPU序列号,如char cpuSerialNumber[20]。 3. 调用系统函数:通过调用相应的系统接口函数,例如在Windows中可以使用WMI(Windows Management Instrumentation)来获取CPU序列号,可以调用GetSystemInfo函数等。在Linux中可以使用/proc/cpuinfo文件来获取CPU信息,可以使用fgets函数读取文件内容。 4. 处理数据:根据具体的获取方式和返回结果,对获取到的CPU序列号进行相应的处理和解析,例如从字符串中提取出序列号部分,并转换为所需的格式。 5. 输出结果:将获取到的CPU序列号打印输出或存储到指定的文件中,例如使用printf函数将序列号输出到控制台。 以下是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> int main() { // 定义CPU序列号变量 char cpuSerialNumber[20]; // 执行操作系统相关的代码,获取CPU序列号 // 以下示例代码仅作范例,实际实现需要根据操作系统和具体接口进行调用和处理 // 假设使用Windows系统,调用GetSystemInfo函数获取序列号 // Windows下获取CPU序列号的代码代码仅仅是个示例 // 实际情况必须根据具体系统和API进行调用和处理 #ifdef _WIN32 // 调用相关API获取CPU序列号 // 以下是一个示例,具体实现需要根据系统和API进行调用和处理 // 此示例代码仅供参考,实际情况请根据具体情况修改 // 示例中的代码可能会有错误,请酌情处理 char* sn; __asm{ mov eax, 1 xor ebx, ebx xor ecx, ecx xor edx, edx cpuid mov sn, edx } sprintf(cpuSerialNumber, "%08X", sn); #elif __linux__ // 调用相关API获取CPU序列号 // 以下是一个示例,具体实现需要根据系统和API进行调用和处理 // 此示例代码仅供参考,实际情况请根据具体情况修改 // 示例中的代码可能会有错误,请酌情处理 FILE *fp; char line[128]; fp = fopen("/proc/cpuinfo", "r"); while (fgets(line, 128, fp) != NULL) { // 判断是否是包含序列号的行 if (strncmp(line, "serial", 6) == 0) { strcpy(cpuSerialNumber, strchr(line, ':') + 2); break; } } fclose(fp); #endif // 输出结果 printf("CPU序列号:%s\n", cpuSerialNumber); return 0; } ``` 请注意,以上代码仅仅是示例代码,实际情况需要根据具体系统和API进行调用和处理,具体的实现方式可能因操作系统、编译器、硬件等因素的不同而有所差异,请酌情调整和修改。 ### 回答3: 获取CPU序列号是一个较为复杂和底层的操作,本身C语言并不直接提供获取CPU序列号的函数或API。要实现获取CPU序列号的功能,可以借助操作系统提供的相关接口。 在Windows操作系统下,可以使用Windows Management Instrumentation (WMI) 的API来获取CPU序列号。以下是一个示例代码: ```c #include <stdio.h> #include <Windows.h> #include <wbemidl.h> #pragma comment(lib, "wbemuuid.lib") int main(void) { HRESULT hres; // 初始化COM库 hres = CoInitializeEx(0, COINIT_MULTITHREADED); if (FAILED(hres)) { printf("Failed to initialize COM library. Error code: %lx\n", hres); return 1; } // 创建IWbemLocator对象 IWbemLocator *pLoc = NULL; hres = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc); if (FAILED(hres)) { printf("Failed to create IWbemLocator object. Error code: %lx\n", hres); CoUninitialize(); return 1; } // 使用IWbemLocator对象连接WMI IWbemServices *pSvc = NULL; hres = pLoc->ConnectServer(_bstr_t(L"ROOT\\CIMV2"), NULL, NULL, 0, NULL, 0, 0, &pSvc); if (FAILED(hres)) { printf("Could not connect to WMI. Error code: %lx\n", hres); pLoc->Release(); CoUninitialize(); return 1; } // 设置连接认证级别 hres = CoSetProxyBlanket(pSvc, RPC_C_AUTHN_WINNT, RPC_C_AUTHZ_NONE, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE); if (FAILED(hres)) { printf("Could not set proxy blanket. Error code: %lx\n", hres); pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; } // 执行WMI查询 IEnumWbemClassObject* pEnumerator = NULL; hres = pSvc->ExecQuery(bstr_t("WQL"), bstr_t("SELECT * FROM Win32_Processor"), WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator); if (FAILED(hres)) { printf("Could not execute WQL query. Error code: %lx\n", hres); pSvc->Release(); pLoc->Release(); CoUninitialize(); return 1; } // 获取查询结果 IWbemClassObject *pclsObj = NULL; ULONG uReturn = 0; while (pEnumerator) { hres = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn); if (uReturn == 0) { break; } VARIANT vtProp; hres = pclsObj->Get(L"ProcessorId", 0, &vtProp, 0, 0); if (FAILED(hres)) { printf("Failed to get ProcessorId. Error code: %lx\n", hres); } else { printf("CPU序列号: %ws\n", vtProp.bstrVal); VariantClear(&vtProp); } pclsObj->Release(); } // 释放资源 pSvc->Release(); pLoc->Release(); pEnumerator->Release(); CoUninitialize(); return 0; } ``` 需要注意的是,以上代码仅适用于Windows操作系统,并且需要在编译时链接`wbemuuid.lib`库文件。在Linux或其他操作系统中,获取CPU序列号的方法可能不同。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值