Why did C use the -> operator instead of reusing the . operator?












4















In the C programming language, the syntax to access the member of a structure is




structure.member




However, a member of a structure referenced by a pointer is written as




pointer->member




There's really no need for two different operators. The compiler knows the type of the left-hand value; if it is a structure, the first meaning is evident. If it is a pointer, the second meaning is evident. Furthermore, . is far easier to type than ->. Not only does -> have more characters to type, on many keyboards one character is unshifted and the other character is shifted, requiring some finger acrobatics. Indeed, many languages based on C allow or use . in place of ->.



Why did C use two operators when one would have sufficed?



(My guess would be because C evolved from the typeless B language.)










share|improve this question


















  • 1





    You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

    – tofro
    3 hours ago













  • @tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

    – Dr Sheldon
    13 mins ago
















4















In the C programming language, the syntax to access the member of a structure is




structure.member




However, a member of a structure referenced by a pointer is written as




pointer->member




There's really no need for two different operators. The compiler knows the type of the left-hand value; if it is a structure, the first meaning is evident. If it is a pointer, the second meaning is evident. Furthermore, . is far easier to type than ->. Not only does -> have more characters to type, on many keyboards one character is unshifted and the other character is shifted, requiring some finger acrobatics. Indeed, many languages based on C allow or use . in place of ->.



Why did C use two operators when one would have sufficed?



(My guess would be because C evolved from the typeless B language.)










share|improve this question


















  • 1





    You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

    – tofro
    3 hours ago













  • @tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

    – Dr Sheldon
    13 mins ago














4












4








4








In the C programming language, the syntax to access the member of a structure is




structure.member




However, a member of a structure referenced by a pointer is written as




pointer->member




There's really no need for two different operators. The compiler knows the type of the left-hand value; if it is a structure, the first meaning is evident. If it is a pointer, the second meaning is evident. Furthermore, . is far easier to type than ->. Not only does -> have more characters to type, on many keyboards one character is unshifted and the other character is shifted, requiring some finger acrobatics. Indeed, many languages based on C allow or use . in place of ->.



Why did C use two operators when one would have sufficed?



(My guess would be because C evolved from the typeless B language.)










share|improve this question














In the C programming language, the syntax to access the member of a structure is




structure.member




However, a member of a structure referenced by a pointer is written as




pointer->member




There's really no need for two different operators. The compiler knows the type of the left-hand value; if it is a structure, the first meaning is evident. If it is a pointer, the second meaning is evident. Furthermore, . is far easier to type than ->. Not only does -> have more characters to type, on many keyboards one character is unshifted and the other character is shifted, requiring some finger acrobatics. Indeed, many languages based on C allow or use . in place of ->.



Why did C use two operators when one would have sufficed?



(My guess would be because C evolved from the typeless B language.)







c






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 3 hours ago









Dr SheldonDr Sheldon

1,9062832




1,9062832








  • 1





    You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

    – tofro
    3 hours ago













  • @tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

    – Dr Sheldon
    13 mins ago














  • 1





    You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

    – tofro
    3 hours ago













  • @tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

    – Dr Sheldon
    13 mins ago








1




1





You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

– tofro
3 hours ago







You can still write (*structure).member, if you like that more. (I don't, very probably K&R didn't, either. It is a bit awkward to handle because of C operator precedence, and that might answer your question)

– tofro
3 hours ago















@tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

– Dr Sheldon
13 mins ago





@tofro: True, such a form always was possible, and avoids introducing another operator. However, it is far worse in terms of finger acrobatics and (as BrianH points out) readability.

– Dr Sheldon
13 mins ago










2 Answers
2






active

oldest

votes


















6














I think there are two factors that led to standardization of the distinct operator "->" for accessing data members using a pointer.




  1. You assume that the C compiler would recognize the type of the LHS as being a pointer. But programmers could, and often did, override the initial typing (variable declaration) by using a typecast.

  2. In order to make the code more readable and less prone to unintended side-effects, it is useful to distinguish operations using pointers.


A very common feature of idiomatic C code is that a structure passed to a function as a pointer is modified within the function. Thus, the result is returned implicitly, by the side-effect of the structure variable in the calling function having been modified by the callee. This sort of approach violates modern sensibilities about loosely coupled code, but it was a simple and efficient means of dealing with complexity in C code. I would say the programmer was greatly assisted in maintaining the readability of such code by having distinct operations that made it clear whether some (possibly shared) memory pointer was the thing whose target was being modified.






share|improve this answer


























  • Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

    – Dr Sheldon
    2 hours ago













  • @DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

    – Brian H
    2 hours ago





















6














In the embryonic form of C described in the 1974 C Reference Manual, there was no requirement that the left operand of . actually be a structure, nor that the left operand of -> actually be a pointer. The -> operator meant "interpret the value of the left operand as a pointer, add the offset associated with the indicated structure member name, and dereference the resulting pointer as an object of the appropriate type. The . operator effectively took the address of the left operand and then applied ->.



Thus, given:



struct q { int x, y; };
int a[2];


the expressions a[0].y and a[0]->y would be interpreted in a fashion equivalent to ((struct q*)&a[0])->y and ((struct q*)a[0])->y, respectively.



If the compiler had examined the type of the left operand to the . operator, it could have used that to select between the two behaviors for it. It was probably easier, however, to have two operators whose behaviors didn't depend upon the left operand's type.






share|improve this answer
























  • To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

    – Raffzahn
    28 mins ago












Your Answer








StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "648"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
noCode: true, onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f10812%2fwhy-did-c-use-the-operator-instead-of-reusing-the-operator%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









6














I think there are two factors that led to standardization of the distinct operator "->" for accessing data members using a pointer.




  1. You assume that the C compiler would recognize the type of the LHS as being a pointer. But programmers could, and often did, override the initial typing (variable declaration) by using a typecast.

  2. In order to make the code more readable and less prone to unintended side-effects, it is useful to distinguish operations using pointers.


A very common feature of idiomatic C code is that a structure passed to a function as a pointer is modified within the function. Thus, the result is returned implicitly, by the side-effect of the structure variable in the calling function having been modified by the callee. This sort of approach violates modern sensibilities about loosely coupled code, but it was a simple and efficient means of dealing with complexity in C code. I would say the programmer was greatly assisted in maintaining the readability of such code by having distinct operations that made it clear whether some (possibly shared) memory pointer was the thing whose target was being modified.






share|improve this answer


























  • Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

    – Dr Sheldon
    2 hours ago













  • @DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

    – Brian H
    2 hours ago


















6














I think there are two factors that led to standardization of the distinct operator "->" for accessing data members using a pointer.




  1. You assume that the C compiler would recognize the type of the LHS as being a pointer. But programmers could, and often did, override the initial typing (variable declaration) by using a typecast.

  2. In order to make the code more readable and less prone to unintended side-effects, it is useful to distinguish operations using pointers.


A very common feature of idiomatic C code is that a structure passed to a function as a pointer is modified within the function. Thus, the result is returned implicitly, by the side-effect of the structure variable in the calling function having been modified by the callee. This sort of approach violates modern sensibilities about loosely coupled code, but it was a simple and efficient means of dealing with complexity in C code. I would say the programmer was greatly assisted in maintaining the readability of such code by having distinct operations that made it clear whether some (possibly shared) memory pointer was the thing whose target was being modified.






share|improve this answer


























  • Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

    – Dr Sheldon
    2 hours ago













  • @DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

    – Brian H
    2 hours ago
















6












6








6







I think there are two factors that led to standardization of the distinct operator "->" for accessing data members using a pointer.




  1. You assume that the C compiler would recognize the type of the LHS as being a pointer. But programmers could, and often did, override the initial typing (variable declaration) by using a typecast.

  2. In order to make the code more readable and less prone to unintended side-effects, it is useful to distinguish operations using pointers.


A very common feature of idiomatic C code is that a structure passed to a function as a pointer is modified within the function. Thus, the result is returned implicitly, by the side-effect of the structure variable in the calling function having been modified by the callee. This sort of approach violates modern sensibilities about loosely coupled code, but it was a simple and efficient means of dealing with complexity in C code. I would say the programmer was greatly assisted in maintaining the readability of such code by having distinct operations that made it clear whether some (possibly shared) memory pointer was the thing whose target was being modified.






share|improve this answer















I think there are two factors that led to standardization of the distinct operator "->" for accessing data members using a pointer.




  1. You assume that the C compiler would recognize the type of the LHS as being a pointer. But programmers could, and often did, override the initial typing (variable declaration) by using a typecast.

  2. In order to make the code more readable and less prone to unintended side-effects, it is useful to distinguish operations using pointers.


A very common feature of idiomatic C code is that a structure passed to a function as a pointer is modified within the function. Thus, the result is returned implicitly, by the side-effect of the structure variable in the calling function having been modified by the callee. This sort of approach violates modern sensibilities about loosely coupled code, but it was a simple and efficient means of dealing with complexity in C code. I would say the programmer was greatly assisted in maintaining the readability of such code by having distinct operations that made it clear whether some (possibly shared) memory pointer was the thing whose target was being modified.







share|improve this answer














share|improve this answer



share|improve this answer








edited 2 hours ago

























answered 3 hours ago









Brian HBrian H

18.3k69156




18.3k69156













  • Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

    – Dr Sheldon
    2 hours ago













  • @DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

    – Brian H
    2 hours ago





















  • Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

    – Dr Sheldon
    2 hours ago













  • @DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

    – Brian H
    2 hours ago



















Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

– Dr Sheldon
2 hours ago







Could you give an example of your point #1? The type of the result of a typecast is well-defined... it's the type you are typecasting to. Should that be a pointer to a structure, the compiler has enough information to access its members. Whatever the type was prior to the typecast is irrelevant.

– Dr Sheldon
2 hours ago















@DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

– Brian H
2 hours ago







@DrSheldon Yes, you are correct. The compiler can check operators used against the type of a typecast too, and interpret a single operator appropriately. But then you are removing one of the compiler checks against programming errors. I think #1 and #2 actually work in concert to push the programmer toward care with pointer references. If the compiler tries to be "too smart" it ends up misinterpreting what the error-prone programmer intended, and (perhaps more important) makes the code harder to read.

– Brian H
2 hours ago













6














In the embryonic form of C described in the 1974 C Reference Manual, there was no requirement that the left operand of . actually be a structure, nor that the left operand of -> actually be a pointer. The -> operator meant "interpret the value of the left operand as a pointer, add the offset associated with the indicated structure member name, and dereference the resulting pointer as an object of the appropriate type. The . operator effectively took the address of the left operand and then applied ->.



Thus, given:



struct q { int x, y; };
int a[2];


the expressions a[0].y and a[0]->y would be interpreted in a fashion equivalent to ((struct q*)&a[0])->y and ((struct q*)a[0])->y, respectively.



If the compiler had examined the type of the left operand to the . operator, it could have used that to select between the two behaviors for it. It was probably easier, however, to have two operators whose behaviors didn't depend upon the left operand's type.






share|improve this answer
























  • To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

    – Raffzahn
    28 mins ago
















6














In the embryonic form of C described in the 1974 C Reference Manual, there was no requirement that the left operand of . actually be a structure, nor that the left operand of -> actually be a pointer. The -> operator meant "interpret the value of the left operand as a pointer, add the offset associated with the indicated structure member name, and dereference the resulting pointer as an object of the appropriate type. The . operator effectively took the address of the left operand and then applied ->.



Thus, given:



struct q { int x, y; };
int a[2];


the expressions a[0].y and a[0]->y would be interpreted in a fashion equivalent to ((struct q*)&a[0])->y and ((struct q*)a[0])->y, respectively.



If the compiler had examined the type of the left operand to the . operator, it could have used that to select between the two behaviors for it. It was probably easier, however, to have two operators whose behaviors didn't depend upon the left operand's type.






share|improve this answer
























  • To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

    – Raffzahn
    28 mins ago














6












6








6







In the embryonic form of C described in the 1974 C Reference Manual, there was no requirement that the left operand of . actually be a structure, nor that the left operand of -> actually be a pointer. The -> operator meant "interpret the value of the left operand as a pointer, add the offset associated with the indicated structure member name, and dereference the resulting pointer as an object of the appropriate type. The . operator effectively took the address of the left operand and then applied ->.



Thus, given:



struct q { int x, y; };
int a[2];


the expressions a[0].y and a[0]->y would be interpreted in a fashion equivalent to ((struct q*)&a[0])->y and ((struct q*)a[0])->y, respectively.



If the compiler had examined the type of the left operand to the . operator, it could have used that to select between the two behaviors for it. It was probably easier, however, to have two operators whose behaviors didn't depend upon the left operand's type.






share|improve this answer













In the embryonic form of C described in the 1974 C Reference Manual, there was no requirement that the left operand of . actually be a structure, nor that the left operand of -> actually be a pointer. The -> operator meant "interpret the value of the left operand as a pointer, add the offset associated with the indicated structure member name, and dereference the resulting pointer as an object of the appropriate type. The . operator effectively took the address of the left operand and then applied ->.



Thus, given:



struct q { int x, y; };
int a[2];


the expressions a[0].y and a[0]->y would be interpreted in a fashion equivalent to ((struct q*)&a[0])->y and ((struct q*)a[0])->y, respectively.



If the compiler had examined the type of the left operand to the . operator, it could have used that to select between the two behaviors for it. It was probably easier, however, to have two operators whose behaviors didn't depend upon the left operand's type.







share|improve this answer












share|improve this answer



share|improve this answer










answered 41 mins ago









supercatsupercat

8,305942




8,305942













  • To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

    – Raffzahn
    28 mins ago



















  • To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

    – Raffzahn
    28 mins ago

















To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

– Raffzahn
28 mins ago





To the point. As well as the last part about being 'easier'. C wasn'T designed to be a language as comfortable as possible, but to be translated as linear as possible. Resolving contextual information adds complexity and ambiguity. Nothing one wants t have when the task is to write an OS as close to the machine as possible while having the luxury of structured programming support.

– Raffzahn
28 mins ago


















draft saved

draft discarded




















































Thanks for contributing an answer to Retrocomputing Stack Exchange!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fretrocomputing.stackexchange.com%2fquestions%2f10812%2fwhy-did-c-use-the-operator-instead-of-reusing-the-operator%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Wolfgang Unzicker

Unua mondmilito

Schloss Hohenburg (Lenggries)