您好我是自我研究C并且我对以下代码感到有点困惑,因为我不知道我是否正确理解了代码。如果有人能够阅读我的解释并在我错了的情况下纠正我,我将非常感激。
代码来自头文件。程序的功能在这一点上应该是无趣的,因为我的理解问题是关于指针和函数返回的值。首先,我在我的员工结构中声明了3个char数组和一个整数。
struct employee
{
char firstname[11];
char lastname[11];
char number[11];
int salary;
}
在头文件中声明了5个函数。第一个函数接受4个值(3个指针和1个int)并返回指向结构的指针。第二个函数获取指向“struct employee”的指针,返回一个指针指向struct employee中数组“char firstname”的元素。函数3和4对于其他两个数组都是相同的。
函数5得到一个指向struct employee的指针,但是返回一个int 而不是指针。所以它只是在结构中使用声明的变量。
struct employee* createEmployee(char*, char*, char*, int); //1
char* firstname (struct Employee*); //2
char* lastname (struct Employee*); //3
char* number (struct Employee*); //4
int salary (struct Employee*); //5
答案 0 :(得分:2)
几乎是正确的,除非你读取函数,输入“char *”应该被读作为字符串传入,虽然技术上它是一个指针。对于整数,实际值是通过的,所以你就在那里。
所以,
struct employee* createEmployee(char*, char*, char*, int);
意味着该过程创建了一个传递了四个输入的员工(前三个是字符串(Char *),可能是该名称的姓氏,姓氏和编号/ ID,最后一个是工资。)
答案 1 :(得分:2)
您的理解非常正确。为了更准确和/或更少滥用英语,函数2-4将指针返回到相应数组的元素。
这个想法是每个数组的内容代表某种文本,每个元素对应一个文本字符,直到第一次出现零值(用于标记“字符串”的结尾)。请记住,这里没有提供Unicode,甚至没有规定编码:我们假设是ASCII,对于不在0..127范围内的任何字节,所有的赌注都是关闭的。类型char
的更好名称是byte
;但那时我们真的不知道更好。 (您还应该知道,char
是与signed char
和unsigned char
分开的单独类型,char
可能会签名也可能不签名。)
这样,名称和数字可以是任意长度直到十(保留第11个字节以便为具有零值的“null终结符”留出空间),并且返回指针可用于检查 - 和修改;但这可能不是一个好主意 - 数组中的数据是Employee
结构的一部分。
int
返回Employee
salary
struct
是结构中的副本。因此,虽然我们可以看到整个值,但不让我们修改结构中的值。当然,只要我们有Employee
定义和struct Employee;
实例,就没有保护;我们可以直接访问该成员,而不是通过该功能。
在C中,我们通过提供这些定义的而非获得“封装”和“数据隐藏”。相反,我们只需将Employee
和函数声明放在头文件中,将结构定义放在实现文件中。现在调用代码并不了解{{1}} 的内容;只关于可以做什么。
答案 2 :(得分:1)
通过读取函数签名,您无法确定返回的值/指针是否引用了来自sturct的相同值/指针,或者函数是创建副本并返回指向新值的指针。这就是为什么在头文件中将文档编写为带有函数签名的注释的好主意。
答案 3 :(得分:1)
你的解释是有道理的,除了#2-4:因为它们返回char*
,它们不能返回一个char数组的元素(后者的正确类型就是{ {1}})。三个函数中的每一个都返回指向char 的指针。有人假设它们将指针返回到相应数组的第一个元素,这基本上就是如何在C中传递数组。
答案 4 :(得分:1)
1中存在问题。我假设你做的是:
struct employee* createEmployee(const char* f, const char* l, const char* n,
const int sal)
{
struct employee* e;
strcpy(e->firstname, f);
strcpy(e->lastname, l);
/* ... */
return e;
}
这里的问题是数组进来。任何大小的char数组都可以传入;这是完全可行的。超过11的任何内容都会导致您开始覆盖&(e->firstname[0])+11;
的数据。什么?究竟。你不知道(也没有我,它会在运行时确定)。这可能会导致一些严重的问题。
另一种方法是使用stdlib.h
和string.h
中的函数,即strlen()
来测试传入的数据的长度,以确保它符合您的字段大小。
更好的方法可能是写:
int createEmployee(struct employee* e, const char* f, const char* l, const char* n,
const int sal)
{
int error = 0;
if ( strlen(f) < 11 )
{
strncpy(e->firstname, f);
}
else
{
error++;
}
/* ... */
return error;
}
看看我做了什么?是的它会工作 - 任何传入的东西都可以修改指针。它不是通过参考传递的。编辑:正如aix所说,指针是“如何在C中传递数组”。
另一种可能的方法是strncpy()
,它将根据最后一个参数截断源字符串,因此strncpy(e->firstname, f, 11);
是安全的。
您也可以根据需求尝试对字段大小进行动态内存分配。我猜你以后会学到这个/作为另一个挑战。
另外,我们的另一个建议是使用typedef定义指向struct的指针。它使事情变得更具可读性,尽管你已经完成它的方式对于某些学习者来说肯定更清晰。