注1:我不是在寻找不同的解决方案。我很好奇这里发生了什么。
注2:我在c ++上下文中这样做,但我假设这也适用于C,因此也适用于C标签。 (除了空指针的表示)
这是关于c-strings和从函数访问原始文件。我将使用argv和argc来说明数组应该是nullptr终止的。我声明他们是这样的:
int argc = 1;
char **argv = (char**) malloc( (argc + 1) * sizeof(char*) );
argv[0] = (char*)"argument 0";
argv[1] = nullptr;
如果我声明这样的函数:func1(int &f_argc, char **f_argv)
我可以访问函数范围内的所有元素,包括f_argv[f_argc]
,nullptr
,但我无法修改原始{{1}指向一个不同的地址,因为函数中的f_argv是一个传递原始指针副本的值。它在内存中有不同的地址。
如果我声明这样的函数:argv
,我可以在函数中访问原始func2(int &f_argc, char ***f_argv)
到argv
,但是最后一个元素(应该是*f_argv
}被切断了。这意味着如果我尝试检查函数内的终止nullptr
,我会尝试访问数组范围之外的元素,从而在运行时生成核心转储。
问题1:为什么在func2中到达nullptr
时f_argv
会被切断,但在func1中却没有?
Q2:有没有办法从函数中获取原始nullptr
的写入权限,而无需删除终结符?
编辑:(添加代码以显示我的意思)
argv
如果运行func2,则运行该程序会在此行导致核心转储:
#include <iostream>
#include <cstring>
void func1(int &f_argc, char **f_argv) {
using std::cout;
using std::endl;
cout << " In function:" << endl;
cout << " argv passed as **f_argv" << endl;
cout << " f_argv = " << f_argv << " , &f_argv = " << &f_argv << endl;
for (int pos = 0; pos < f_argc; pos++) {
if (f_argv[pos] != nullptr) {
cout << " f_argv[" << pos << "] = \"" << f_argv[pos] << "\"" << endl;
} else {
cout << " f_argv is prematurely terminated" << endl;
}
}
if (f_argv[f_argc] == nullptr) {
cout << " f_argv is correctly terminated" << endl;
} else {
cout << " f_argv[" << f_argc << "] = \"" << f_argv[f_argc] << "\"" << endl;
cout << " f_argv is not terminated" << endl;
}
// Intention is to copy argv here, add elements, terminate it with
// nullptr and change original argv to point to copy. This wouldn't
// work in this function, as &f_argv != &argv.
return;
}
void func2(int &f_argc, char ***f_argv) {
using std::cout;
using std::endl;
cout << " In function:" << endl;
cout << " array passed as ***f_argv" << endl;
cout << " f_argc = " << f_argc
<< " , &f_argc = " << &f_argc << endl;
cout << " *f_argv = " << *f_argv
<< " , f_argv = " << f_argv << endl;
for (int pos = 0; pos < f_argc; pos++) {
cout << " about to check: "
<< "if (*f_argv[" << pos << "] != nullptr)" << endl;
if (*f_argv[pos] != nullptr) {
cout << " *f_argv[" << pos << "] = \""
<< *f_argv[pos] << "\"" << endl;
} else {
cout << " *f_argv is prematurely terminated" << endl;
}
}
if (*f_argv[f_argc] == nullptr) {
cout << " *f_argv is correctly terminated" << endl;
} else {
cout << " *f_argv[" << f_argc << "] = \""
<< *f_argv[f_argc] << "\"" << endl;
cout << " *f_argv is not terminated" << endl;
}
// Intention is to copy argv here, add elements, terminate it with
// nullptr and change original argv to point to copy.
return;
}
// --------------------------------------------
int main() {
using std::cout;
using std::endl;
int argc=1;
char **argv = (char**) malloc( (argc + 1) * sizeof(char*) );
argv[0] = (char*)"argument 0";
argv[1] = nullptr;
cout << "Before function call" << endl;
cout << "argv = " << argv << " , &argv = " << &argv << endl;
for (int i = 0; i < argc; i++) {
if (argv[i] != nullptr) {
cout << "argv[" << i << "] = \"" << argv[i] << "\"" << endl;
} else {
cout << "argv is prematurely terminated" << endl;
}
}
if (argv[argc] == nullptr) {
cout << "argv is correctly terminated" << endl;
} else {
cout << "argv[" << argc << "] = \"" << argv[argc] << "\"" << endl;
cout << "argv is not terminated" << endl;
}
// run one of these
//func1(argc, argv);
func2(argc, &argv);
free(argv);
return 0;
}
答案 0 :(得分:3)
下标运算符的优先级高于解除引用运算符。 *f_argv[f_argc]
是*(f_argv[f_argc])
。你想要的是(*f_argv)[f_argc]
。
由于您使用的是C ++,因此您应该考虑通过引用f_argv
- void f(int &f_argc, char **& f_argv);
。