5 ms·
Does anyone know why C calls like 'strcpy' and 'strcat' are the opposite of this? strcat(target, source) strcpy(target, source) But, in SH... cp source
by dboyd 16y ago
Does anyone know why C calls like 'strcpy' and 'strcat' are the opposite of this?
strcat(target, source)
strcpy(target, source)
But, in SH...
cp source target
I feel like these things were developed around the same time, by the same community. I've always wondered if there was a reason for the different perspective.
- jat850 16y agoI suspect strcat and strcpy were parameterized as such to match memcpy. Why memcpy was parameterized in that order, I am not certain.
- aliguori 16y agomemcpy(lvalue, rvalue, size) lvalue == write location rvalue == read location It comes from assignment syntax where the left hand side is the target of the assignment and the right hand side is the source. So this makes a ton of sense in C. OTOH, the Bourne shell was built independent of the C programming language. The Bourne shell inherited a bit from its predecessor the Thompson shell which introduce the concept of command piping. In this case, all operations followed the pattern of data flowing to the right. This is the opposite of how assignment works in all programming languages where data flows to the left. That's why shell commands generally move data from left to right based on their argument ordering. FWIW, tar is unique because tar wasn't meant to do archiving to files. If you just did `tar c directory' it would archive the directory to a tape device. The `f' flag is there to redirect the output to a file (instead of the default tape device). So `tar cf foo.tar directory' is not backwards, it just uses an unusual argument convention. The modern form would be `tar --file=foo.tar create directory'.
- Sharlin 16y agoProbably in order to be consistent with assignment.
- aliguori 16y agoWhich is really the odd ball. In a left-to-right language, it's sort of bizarre that we don't write `4 = x' since the rvalue tends to be the more complicated part of the expression. The curious bit is, AT&T assembly syntax does follow this convention so you'll see something like `mov $5, ax'.
- rlpb 16y agoI think it's more to do with the requirement that mandatory arguments have to go before optional ones (it wouldn't work the other way round).
- Sharlin 16y agoIn strcpy, memcpy and partners, both arguments are (rather obviously) mandatory...
- yagibear 16y agoPossibly for consistency with functions that take varargs, e.g. sprintf
- fluidcruft 16y agoIt's similar to all the file I/O functions that always have the file descriptor first (fprintf etc). These are the heart of Unix. Remember the Unix philosophy: Everything is a file.* * for a slightly smaller definition of everything than in Plan9
- philwelch 16y agoThis is a crime against usability IMO. Another comment mentioned that tar takes arguments as "target source" rather than "source target". Ever notice that for everything in the world that screws, like valves or screws or bottle caps, counter-clockwise loosens and clockwise tightens? How is it we got the whole world to agree on that convention, but software is 50/50 on how we order the source and destination?
- jonsen 16y agoExcept volume dials.
- philwelch 16y agoAnd sometimes doorknobs, but those are abstract enough you wouldn't expect them to behave the same. Unless you're talking about screwing the dial itself clean off.
- joeyh 16y agoAnd gas valves.
- jholman 16y agoI conclude from this, by process of logical inference, that "louder" must be a type of "tighter". "Forward" is also "tighter", apparently.
- joshu 16y agotar is like that because of command lines tar [args] [one thing] [list of things] it'd be wierd if it was tar [args] [list of things] [filename] ... but i will admit i frequently make that mistake.
- ramidarigaz 16y agoBut, as a counterpoint, if you want to copy several things to a folder, you do: cp [args] [list of things] [destination folder]
- jonsen 16y agoMost assemblers have fx mov a,b as from b to a.
- alain94040 16y agoThe reason strcat, strcpy have the destination first is because of the need to support a variable number of arguments. By definition, if the number of arguments is variable, they must be at the end. So if you think of sprintf for instance, the destination has to be first. Now, to be consistent, strcat has to behave the same and have the destination first as well, although it doesn't have a variable number of arguments.
- Sharlin 16y agoI'm pretty sure strcpy et al pre-date the introduction of varargs. Besides, there's no reason the format string couldn't be the last argument of printf, except the specific technical detail that C requires at least one mandatory argument in any variadic function (the variable's address is used to locate the optional arguments in the stack.)
- davidcuddeback 16y agoOn a machine's runtime stack, there is no indication of how many parameters were passed to the function (at least on x86). C functions must use one of the mandatory arguments to determine how many arguments were pushed on the stack. In the case of the printf-family of functions, it's the number of format specifiers, e.g., "%d".
- bobbyi 16y agoSimilar confusion arises from the AT&T and Intel syntaxes for x86 assembly which differ in the order of operands: Intel: mov bx, 100 AT&T: mov $100, %bx http://en.wikipedia.org/wiki/X86_assembly_language#Syntax http://en.wikipedia.org/wiki/X86_assembly_language#Syntax
- tialys 16y agoSomeone once said to "What you have, then what you want" which made ALL of these easier to remember for me. In the case of strcat/cpy I think it still follows: I have an empty string 'target' and I'd like it to be 'source'.
- ajays 16y agoC calls are trying to mirror the assignment statement in the programming language: target := source "cp" is trying mirror how we do things in real life: if you want to take some things from one place and put them in another, you first pick them all up (hence the first argument), walk over to the destination, and then put them down.
- Someone 16y agoI always think that you get strcpy by first writing *target = source* Step two is realizing that things don't work that way in C. Step three is sprinkling in semantic sugar to make it work. strcat, then, is for symmetry with strcpy.