11 ms·
Where do argc and argv come from?
- vidanay 6y agoI feel like the article does not address the stated question. arg(ument) c(ount) and arg(ument) v(ector) is what I was taught. edit: After a re-read, the article is about where the actual values come from and not the historical semantic meaning of the variable names.
- sillysaurusx 6y agoI was just as interested in the etymology.
- globuous 6y agoMe too, I once knew it but looked it up again earlier today out of curiosity. I was actually quite surprised to see this thread popup on HN a few hours later!
- zabzonk 6y agoAlso, in C (and C++) the names of the parameters are not significant - you could call them x and y and the compiler would be happy.
- vidanay 6y agoIn what language is the name of a method parameter ever significant?
- foota 6y agoAny with named args?
- monocasa 6y agoSmalltalk and ObjC for a couple examples. I wouldn't be surprised to find out Swift was too, but I'm not 100% on that.
- plorkyeran 6y agoThe name of method parameters in obj-c is not significant. The argument label and argument name are different things. In `- (void)frobulateThing:(id)firstThing andAlso:(id)secondThing;`, `firstThing` and `secondThing` are the argument names and can be changed with no impact on the callers, while `frobulateThing:andAlso:` is the part relevant to callers. In Swift the argument labels are the same as the argument names by default, but you can also supply different values for them.
- loopz 6y agoI kinda like the idea of it, or at least have the option to do that. You can name args in python function calls.
- senkora 6y agoPython. Since any argument can be called as a keyword arg, the names of arguments are a part of the API, and renaming them can break user code. I have written bugs because of this.
- loopz 6y agoFor compiled languages, it's neat to get compiler error instead of a nasty bug.
- Karliss 6y agoNo compiler in Python. In combination with features like varargs, kwargs, unpacking dictionary into args, argument forwarding Python allows you to turn this into bugs.
- senkora 6y agoWell, Python does get compiled to bytecode before it is run. And the compiler does tell you about some errors, like inconsistent indentation, even if that code is never executed.
- kortilla 6y agoIn python without explicit analysis using something like pylint you won’t find out until function call time.
- deleted 6y ago[deleted]
- quietbritishjim 6y agoA bug is a problem that affects your users. If you're a library author then your users are developers of applications (and higher-level libraries), so an unintentional breaking change to your API is definitely a bug.
- dotancohen 6y ago
- SilasX 6y agoRuby on Rails. Ugh. (Though yes, that’s a framework rather than a language.)
- deleted 6y ago[deleted]
- inopinatus 6y agoNamed arguments in much of the Rails API are received by the method via a single hash parameter, not as individual lexically bound variables. In most cases, Ruby handles this capture via a double-splat operator in the parameter list. However, Ruby itself does have both positional and named method parameters. The former contribute to arity and may be overridden and renamed in subclasses, and this remains true for Rails methods accepting positional arguments. It is also the case that a hash is implicitly congruent to named arguments, although this is controversial and may change in future. I’m sorry to report that no-one has ever described this as “arg hash” or “argh” for short.
- ufo 6y agoAnother example is Angular.js It used Javascript's toString() method to get the names of the arguments and then did dependency injection magic based on it. Does anyone know if that is still the case for recent versions of Angular?
- bmm6o 6y agoAnd because js is frequently minified, there is a way to specify the names as string literals to keep the injection working.
- staycoolboy 6y agoThat's an easy one: Python. The function declaration can force significant naming, but only for the caller.
- dcminter 6y agoJava (sometimes) where reflection allows you to inspect the parameter names, and you can optionally retain the names in the compiled bytecode. E.g. these days the Spring framework defaults to using the parameter name as the qualifying name to discriminate between otherwise identical types during autowiring.
- DSMan195276 6y agoSince it hasn't been mentioned yet, C#/.NET also has this dumb feature - the name of the parameter is compiled into the dll, and can be used for 'named arguments', where the caller can write `a: 20` in the argument list to assign the parameter called `a` to 20. If the library developer renames the parameter to something other than `a`, than that old code won't compile anymore (Though AFAIK the old compiled code is still ABI compatible with the new version, since the method arguments are resolved at compile time).
- int_19h 6y agoPretty much any language that allows named parameters at call site.
- enriquto 6y agoI prefer to use c and v, to be more explicit.
- srathi 6y agoI thought the same. Now I think it is simply argument-count and argument-values. Not sure if that is correct!
- ChrisSD 6y agoIn the Windows world there is no argc/argv. There is only the commandline string. The C runtime will parse this to emulate the required arguments. The commandline is stored in the process environment block and can be set to anything when the process is created.
- kevin_thibedeau 6y agoYou can make Windows pre-process the command line args and expand globs so that main() works like normal on Unix. It just isn't the default.
- ChrisSD 6y agoThe shell can do whatever processing it likes but at the end of the day all that's passed to the application is a string. The string may or may not be what a user typed but the application has no knowledge of that.
- kevin_thibedeau 6y agoIt isn't done by the shell on Windows.
- ChrisSD 6y agoThe shell is whatever you use as a shell. Be that cmd, powershell or your own invention. My point is that it doesn't matter. The shell can process the command line however it likes but all the application receives is a single string. The application can then do whatever it likes with the string. Sure you can use an entry point that parses the arguments in different ways but that's still the application parsing the string. You're just using a library function to do the parsing instead of doing it manually. At no point does "Windows" do anything. As far as its concerned it's just a string being passed in at process creation.
- mortehu 6y agoIf it's not the shell and not the application, are you saying there's a kernel setting that enables glob expansion? I suspect you're really talking about linking to setargv.obj?
- mywittyname 6y agoIs this something that the compiler normally handles or is it handled by the runtime environment upon executing a program?
- chrisseaton 6y agoThey're part of the language specification - the main function has different semantics to a normal function in a few ways - so the compiler must handle it to some extent.
- oso2k 6y agoNot true. The kernel & shell makes the values available on the stack and the runtime can choose to link to them or not. The ABI also details how and where the values should be placed.
- chrisseaton 6y ago> Not true. Yes true. Check 5.1.2.2.1 and 5.1.2.2.3 in the standard. If you don't treat 'main' specially you won't have a conforming C compiler. It's unique in accepting different signatures, and for its return value syntax and semantics. You cannot just compile it as a normal function and link it with a runtime routine. You need compiler support for it.
- oso2k 6y agoThis is the C Standard specifying its VM to match the assumptions of a *nix environment. `main` isn't so special, IMO. Conformance to the C Standard is always optional, see C++, golang, Rust. However, conformance to ABI is less optional.
- kps 6y ago> You need compiler support for it. There are probably implementations that require compiler support, but it is not required by the standard and not true of many common implementations. Support is by the caller, as described in others' parallel comments. > You cannot just compile it as a normal function and link it with a runtime routine. You can. As a concrete example, for the following two programs, int maim(int argc, char *argv[]) { return 0; } int main(int argc, char *argv[]) { return 0; } the assembly code produced by gcc 9.3 x64 is identical except for the spelling of the identifier.
- ploxiln 6y agoJust in case the author shows up here, there's a confusing little typo in "Passing argv to our program": _start: popq %rdi movq %rsp, %rdi callq main the second %rdi should be %rsi, which is confirmed by the explanatory test: > If it's really that easy all we will need to do is add movq %rsp, %rsi after the popq %rdi we just added. EDIT: now fixed
- dim13 6y agoLooks like a little known fact, but there is a third parameter too: int main(int argc, char **argv, char **envp)
- kps 6y agoNon-portable, though. It's original to Unix and in sufficiently good implementations and clones, but not even required by POSIX.
- jeffrallen 6y agoToo bad the author skips over envp and what comes after... http://dbp-consulting.com/tutorials/debugging/linuxProgramStartup.html http://dbp-consulting.com/tutorials/debugging/linuxProgramSt... mentions something really fun after envp, which is the ELF auxillary info, including a random seed offered by the kernel to seed rand if you want it. See: https://man7.org/linux/man-pages/man3/getauxval.3.html https://man7.org/linux/man-pages/man3/getauxval.3.html
- saagarjha 6y ago> There is a third argument to main Note that on macOS there is an additional fourth argument to main, char *apple[] (I would write this as a double pointer, but Hacker News would eat it if I did). It contains things passed on from the kernel mostly on relevant to libc and dyld.
- nneonneo 6y agoOn Linux, after argc, argv and envp comes the even more mysterious auxv, a key-value store for binary data. The kernel shoves a lot of interesting stuff into auxv, including AT_RANDOM - 16 random bytes (used to construct stack canaries and function pointer encryption keys), AT_HWCAP (processor capability flags), and AT_SECURE (a flag specifying if the program is setuid and therefore security sensitive). Although a lot of it is meant just for internal C library use, it can be helpful for programmers too (e.g. being able to check hardware capabilities without a trip to cpuid).
- cryptonector 6y agoThis is true for ELF, not just Linux. And it need not be true for a.out (IIRC it's not true for a.out executables on Linux or any other Unix or Unix-like OS that supports a.out executable formats). There are a few auxiliary vector keys that are standard per-ELF, and others that are platform-specific. The original purpose of the auxv was to provide the ELF interpreter (ld.so) with information it needs in order to bootstrap.
- skissane 6y ago> IIRC it's not true for a.out executables on Linux I was surprised to discover a.out support is still there in the kernel [1]. There has been talk on LKML about whether to remove it [2] – apparently it has accumulated regression bugs (particularly in the area of core dumping) which nobody has noticed and fixed, which is the inevitable fate of code that hangs around for decades after everybody stops using it – but it still hasn't been removed yet. [1] https://github.com/torvalds/linux/blob/master/fs/binfmt_aout.c https://github.com/torvalds/linux/blob/master/fs/binfmt_aout... [2] https://www.lkml.org/lkml/2019/3/5/389 https://www.lkml.org/lkml/2019/3/5/389
- TallGuyShort 6y agoHuh - I remember using `char env` as the third parameter to main. After a quick Googling, it would seem that's a GCC-specific thing. Surprised there's a Linux-specific (or ELF-specific, as another commented) convention other than that one.
- chenxiaolong 6y agoOne neat thing I learned is that `argv` and `envp` are contiguous on Linux. You can change the process name that appears in `ps` by modifying memory that `argv` elements point to. If you need more space, you can also skip NULL-terminating `argv` so that it will read on into `envp`. Chromium, for example, does this: https://source.chromium.org/chromium/chromium/src/+/master:services/service_manager/embedder/set_process_title_linux.cc;l=130;drc=1be837b6f1420d2ae8ffb47aa46fe78f522eccba https://source.chromium.org/chromium/chromium/src/+/master:s...
- segfaultbuserr 6y agoModifying argv is a classic trick to implement an "error log of last resort" - How can you log an error message when the I/O itself has failed (e.g. the disk is full)? You can write you message to argv. A sysadmin running ps can quickly spot a "FATAL ERROR OCCURRED" argument appears next to the program name. Famously used by DJB in his mail server.
- cryptonector 6y agoThere are OSes where altering `argv[0]` changes the ps strings, and ones where it doesn't. Arranging to support this is tricky, as it can be a way to attack users of ps(1) and /proc!
- saagarjha 6y agoFun fact: iTerm recently had to redesign some of their APIs because the process name APIs would be susceptible to a malicious program overwriting its argv (the normal API for this has the kernel read out of the process's address space).
- jez 6y agoI needed to understand linkers and object loaders for something at work recently, and I can't recommend Computer Systems: A Programmer's Perspective enough![1] It answered a lot of questions I'd always had about computer systems. I jumped straight into Chapter 7: Linking and learned so much that I read a bunch of other chapters for the fun of it. E.g., Chapter 7 covered that the `_start` symbol mentioned in this post is just a symbol in your executable that the Linux executable loader knows to jump to, but it's not the only special symbol! The chapter on linking also covered how loading and linking dynamic/shared libraries works, which was also really cool. I wrote up some of the things I learned about that stuff too.[2] [1] http://www.csapp.cs.cmu.edu/ http://www.csapp.cs.cmu.edu/ [2] https://blog.jez.io/linkers-ruby-c-exts/ https://blog.jez.io/linkers-ruby-c-exts/
- brandmeyer 6y agoAlong the same vein, "How to Write Shared Libraries" by Ulrich Drepper goes into much more detail than you might expect given the title. https://www.akkadia.org/drepper/dsohowto.pdf https://www.akkadia.org/drepper/dsohowto.pdf
- m3047 6y agoI can't find a reference for DEC's PDP processors, but the 68000 (Motorola) processor family had LINK and UNLINK instructions useful for constructing a (calling) stack frame. DEC's later VAX (Virtual Address eXtension) processor line included stack frames baked into the silicon. The CALLS instruction was called with the number of 32 bit arguments previously pushed onto the stack; the CALLG instruction was called with a pointer to a memory structure consisting of an argument count and an argument vector. From the foregoing progression it can be inferred that this idiom was common and deemed a Good Thing by some faction in computer science of the time. As for functions with specific names, when linking against libraries there are typically symbol tables for resolving references between separately compiled modules. As a self-professed (I took out a small display ad in the print publications _Computer World_ and _Asian Computing Monthly_ in 1984) "VAX Hacker for Hire", I made use of C's utter lack of concern for such things by declaring a char* arg and using pointer arithmetic to get the actual count of args to implement optional parameters; I wasn't the only one. Between that and abusing the REF and VAL pragmas in pretty much all DEC programming languages, it was good times.
- bartvk 6y ago> "VAX Hacker for Hire" What did that cost? And was it effective in getting you projects?
- m3047 6y ago1) My recollection was that _Computer World_ was around $400 for two insertions, and _Asian Computer Monthly_ was slightly less for 6. They were small ads. 2) Yes, I did make the acquaintance of a local (!) company, which I ended up having a 10 year relationship with. I also had a few of entertaining inquiries, none of which got me in trouble with the law, but also didn't make me any money. (Know when to say "no".)
- bartvk 6y agoFantastic to hear. 400 bucks is extremely cheap for a long term relationship with a client. Agencies in Europe put 20% on top of your rate.
- sukilot 6y agoWhat's the point of this? If you are writing a C program, get a C book and learn all about argc and argv. Of you know a good C book, post about it to HN. If your aren't writing a C program, this is irrelevant. Why does HN every day pull a random page from a manual and vote it to the front page? This is a terrible way to learn anything.
- saagarjha 6y agoMost C books will not mention the things in this blog post.
- wruza 6y agoThis is the best way though to meet some guys who never wrote a book, but are competent enough to delve into details that barely any book mentions. If you want to know one thing deep, sure, get a book or two. But if you want to create your understanding on numerous topics (wide learning), your way is a very long journey that might not even end before you retire. I don't think someone learns here as in a class, we just discuss matters of our interests. You start with replying to tfa, and then it turns more and more whatever it turns into. Nothing new for a forum-like, really, many do not even need clickable headlines, since they do not click on them.
- gpvos 6y agoIt is relevant if you're writing a linker or compiler, or just interested in what happens behind the scenes.
- xmprt 6y agoYour assumption is that HN is a place to learn things.