嘿所有,我只是想知道是否有可能获得在函数中运行的程序的名称?
以下是一个例子:
说我打电话: ./ runProgram
main() {
A();
}
function A() {
// Possible to retrieve "runProgram" if I cannot use main's argc(argv) constants??
}
答案 0 :(得分:5)
编译器相关,所以:
$ cc --version
i686-apple-darwin10-gcc-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5646)
制作节目
$ more x.c
int main(int argc, char *argv[]) {
printf("program: %s\n", argv[0]);
foo();
}
int foo() {
}
$ make x
cc x.c -o x
x.c: In function ‘main’:
x.c:2: warning: incompatible implicit declaration of built-in function ‘printf’
$ ./x
program: ./x
获取argc / v vars的全局名称
$ nm ./x
0000000100000efe s stub helpers
0000000100001048 D _NXArgc
0000000100001050 D _NXArgv
0000000100001060 D ___progname
0000000100000000 A __mh_execute_header
0000000100001058 D _environ
U _exit
0000000100000eeb T _foo
0000000100000eb8 T _main
U _printf
0000000100001020 s _pvars
U dyld_stub_binder
0000000100000e7c T start
添加全局名称,声明为extern,并考虑到重整。
$ more x2.c
int main(int argc, char *argv[]) {
printf("program: %s\n", argv[0]);
foo();
}
int foo() {
extern char **NXArgv;
printf("in foo: %s\n", NXArgv[0]);
}
运行恐怖
$ make x2
cc x2.c -o x2
x2.c: In function ‘main’:
x2.c:2: warning: incompatible implicit declaration of built-in function ‘printf’
x2.c: In function ‘foo’:
x2.c:9: warning: incompatible implicit declaration of built-in function ‘printf’
$ ./x2
program: ./x2
in foo: ./x2
请不要告诉我的妈妈。
答案 1 :(得分:4)
这在“标准C”中是不可能的。如果您正在使用jiggery-pokery,您可以查看程序的环境变量以查找命令行。以下适用于FreeBSD:
/* _ _ _
(_|_) __ _ __ _ ___ _ __ _ _ _ __ ___ | | _____ _ __ _ _
| | |/ _` |/ _` |/ _ \ '__| | | |_____| '_ \ / _ \| |/ / _ \ '__| | | |
| | | (_| | (_| | __/ | | |_| |_____| |_) | (_) | < __/ | | |_| |
_/ |_|\__, |\__, |\___|_| \__, | | .__/ \___/|_|\_\___|_| \__, |
|__/ |___/ |___/ |___/ |_| |___/ */
#include <stdio.h>
extern char ** environ;
void A ()
{
char ** p;
for (p = environ; *p; p++)
printf ("%s\n", * p);
}
int main ()
{
A ();
}
然而,在C语言本身,与JavaScript和Perl等语言不同,没有办法偷看堆栈并找出谁给你打电话。
答案 2 :(得分:3)
GetCurrentProcessId();
将为您提供当前的进程ID。从那里,您需要将其与当前运行的进程名称进行匹配。
有关步骤2的详细信息,请参阅this code project article。
答案 3 :(得分:1)
通常你要做的就是使用全局变量。
const char *g_argv0;
void A()
{
printf("program is %s\n", g_argv0);
}
int main(int argc, char *argv[])
{
g_argv0 = argv[0];
A();
return 0;
}
如果您需要这个想法,可以将整个命令行数组保存在全局变量中。
答案 4 :(得分:1)
程序名称将存储在argv [0]中。
请注意,这与首先想到的文件名不一定相同。例如,如果有程序的符号链接并且使用该名称调用程序,那么这将存储在argv [0]中。
因此,例如,您可以使用以下程序:
#include <stdio.h>
int main(int argc, char **argv)
{
printf("%s\n", argv[0]);
return 0;
}
会产生以下行为:
$ cc t.c
$ ./a.out
./a.out
$ ln -s a.out foo
$ ./foo
./foo
请注意,在名称到达程序之前会发生shell替换:
$ alias bar=./foo
$ bar
./foo
答案 5 :(得分:0)
忽略上面的代码是可怕的C并且实际上更接近伪代码的事实......
没有。您可以将argv[0]
分配给全局变量,以便可以通过其他地方的代码访问它,也可以将其作为参数传递。我怀疑是否有一种标准的C方式来进入另一个函数的局部变量。这听起来像是一个相当糟糕的主意(以我的拙见)。
使用全局:
char *progname;
void A(void)
{
// do stuff with progname
}
int main(int argc, char **argv)
{
progname = *argv;
A();
return 0;
}
作为论点传递:
void A(char *progname)
{
// do stuff with progname
}
int main(int argc, char **argv)
{
A(*argv);
return 0;
}
编辑:我们大多数人都错过了它,因为它在评论中隐藏着相当具体,但你说你不能使用argv
。我只想指出,任何不使用argv
的解决方案都是不可移植的,最好的答案是继续使用argv
,因为它是由标准给你的,而且没有您无法使用argv
的可能原因。这就像是说“如何在不使用stdin
文件句柄的情况下将文本打印到控制台?”你可以做到,但你为什么要这样做?
答案 6 :(得分:0)
int main(int argc, char *argv[]) {
printf("program: %s\n", argv[0]);
//pass argv[0] to the desired function.
}
答案 7 :(得分:0)
使用Windows,您可以使用GetCommandLine函数。也许Linux有一个类似的API。
答案 8 :(得分:0)
您可能会找到导致您的进程从getpid执行的完整命令,但有关如何执行此操作的具体信息因平台而异。
答案 9 :(得分:0)
在Linux下,您可以查看/proc/self/cmdline
(或者使用getpid()
查找进程ID,然后查看/proc/[pid]/cmdline
;前者是后者的快捷方式。
答案 10 :(得分:0)
x86上的C调用约定具有这样的堆栈帧布局。
... *0x4000000c = 0x60000000 (2nd argument) *0x40000008 = 0x00000001 (1st argument) *0x40000004 = 0x20000000 (return address) *(old %esp = %ebp = 0x40000000) = 0x3ffffff0 (old %ebp) *0x3ffffffc = 0x00000000 (1st local) *0x3ffffff8 = 0x00000000 (2nd local) ... *(%esp = 0x3ffffff0) (end of frame)
因此,要获得调用者的参数,请从(%ebp)
开始并向上走。 GCC的__builtin_frame_address
扩展有助于迈出第一步。
A() {
void **ebp = __builtin_frame_address(1);
void **ra = ebp + 1;
int *argc = ra + 1;
char ***argv = argc + 1;
int i;
for (i = 0; i < *argc; i++) printf("[%d] %s\n", i, (*argv)[i]);
}
a(int argc, char **argv) { A(); }
main(int argc, char **argv) { a(argc, argv); }
不幸的是,main
有点特殊,因此直接从A
调用main
可能会崩溃。
此外,为了节省工作并释放寄存器,优化编译器可能会省略此标准堆栈帧设置,这也会导致失败。