int *p vs int* p Pointer Declarations | C Programming Tutorial

  Рет қаралды 142,034

Portfolio Courses

Portfolio Courses

Күн бұрын

Пікірлер: 568
@PortfolioCourses
@PortfolioCourses 11 ай бұрын
The comments suggesting declaring one variable per line as the better/ultimate solution are spot on, I've made this video covering the advantages of this style: kzbin.info/www/bejne/maa1dHiQpdSnfq8. The videos on this channel are mostly targeted at beginners, such as students taking C Programming 101 courses, and I made this video in response to comments asking about the star when declaring multiple pointers... i.e. what is going on here, what does the star do, do we need more than one star, what way should we do it? For some reason the KZbin algorithm decided to promote this video like wild over the last week... I'm genuinely shocked, in almost 3 years of doing this channel it's never done that before. So if you're new to the channel, welcome aboard! The videos here do target beginners coming to KZbin with "school exercise" type questions, so things like %d vs. %zu, how types can be different sizes depending on the machine/compiler, etc, aren't covered in every video (though there are videos covering topics that are generally beyond a typical C Programming 101 course, like sizeof(), size_t, pthreads, etc.). There are some really good channels covering C programming in more depth if you're looking for that (Low Level Programming, Jacob Sober, CodeVault). 🙂 If you do like these videos, check out these C programming playlists with hundreds of videos! 🙂 C Programming Examples: kzbin.info/aero/PLA1FTfKBAEX6dPcQitk_7uL3OwDdjMn90 C Programming Tutorials: kzbin.info/aero/PLA1FTfKBAEX4hblYoH6mnq0zsie2w6Wif
@TheBunzinator
@TheBunzinator 11 ай бұрын
I've always considered this to be a failure of the language definition. An int is clearly a different data type than a pointer to an int, so the * should be part of the type, not the variable name. Therefore, I always use int* i;, and never do multiple variable decls on the same line.
@higgins007
@higgins007 11 ай бұрын
This, precisely. Agree.
@RahulYadav-hq2yy
@RahulYadav-hq2yy 11 ай бұрын
You need to call *p to dereference the pointer and access the int. So *p is an int. Now `int *p` makes more sense, doesn't it. At least it helps me understand how to think about it. I agree the language could have been better about this though
@dominiccasts
@dominiccasts 11 ай бұрын
True, but at the same time p is an int*, so int* p makes the same amount of sense for that syntax
@CybAtSteam
@CybAtSteam 11 ай бұрын
Same here, "int-pointer p" has always made more sense than "int pointer-p"
@Colaholiker
@Colaholiker 11 ай бұрын
I am on the same team here. Also, literally EVERY established coding standard disallows or at least discourages multiple variable declarations per line. Therefore, the problem shown in the video is accurate but shouldn't happen in the first place. I guess the only reason why this has never been cleaned up are gazillions of lines of legacy code that used more than one variable declaration per line, happily mixing variables of the actual type and pointers to variables of the type in one line. You know, that kind of code that gives C a bad name... I will stick with my "type* variable_name" style, no matter what. It's like the toilet paper roll thing. There is only one correct way to put it on the holder, but some people still think it must be the other way around. 😂
@bewingbewing
@bewingbewing 11 ай бұрын
As old (or, excuse me, mature) as C is, there's still no end of the mayhem you can create! Or, as my friend says: C is happy to let you put it into reverse at 60 MPH. Thanks for this clear and concise video.
@Valerius123
@Valerius123 11 ай бұрын
C is probably becoming more relevant now than it has been the last 20 years simply because people are starting to come out of the OOP stupor they've been in. Rust and C. Use Rust for security centric applications and C elsewhere.
@kellyfrench
@kellyfrench 11 ай бұрын
If c had a motto, it would be, “you know what you are doing, I hope”
@Valerius123
@Valerius123 11 ай бұрын
@@kellyfrench The worst part about C is libc and all the inherently unsafe functions it provides. If we kept the same language but provided a safer and more fully featured standard library that came packaged with gcc or clang I'm sure people would not dislike C as much as they currently do.
@zecuse
@zecuse 10 ай бұрын
Sure, those structs have the same size. Here's this one cast as that one. Have fun with the runtime error of the non-null terminated string!
@TotoMacFrame
@TotoMacFrame 10 ай бұрын
Best comment I have heard to far, gave me a good laugh 😄
@danielsass4134
@danielsass4134 11 ай бұрын
I have always preferred int* p, because when I first learned C, I would get confused between declaring a pointer to an integer and dereferencing a pointer. It was easier in my head to remember that int* is a pointer to an integer and *p is dereferencing a pointer. Nevertheless, I understand your point-of-view and neither notation bothers me anymore.
@CYXXYC
@CYXXYC 11 ай бұрын
its kinda because authors of the language(s) meant that `int *p` means that you will use it as `*p`, same for `int p[...]` allowing for `p[...]` and other syntax constructions
@yiyuzhou3453
@yiyuzhou3453 11 ай бұрын
I’m the opposite, because I think of it as *p is type int.
@hansdampf2284
@hansdampf2284 11 ай бұрын
Think about this again. The dereferenced p is and int. So p is the pointer and *p is an int. Therefore int *p makes perfect sense.
@HaydenLikeHey
@HaydenLikeHey 11 ай бұрын
I still use this to this day and was backed up in it by a video from Brian Will. He suggests that we shouldn’t even think of int* as a “pointer to an integer” but rather as an “integer pointer type variable.” Viewing pointers as types helped me fully separate them in my mind from dereferencing operations when mutating data.
@antonhelsgaun
@antonhelsgaun 11 ай бұрын
​@@hansdampf2284but int* p also makes sense, because p is an int pointer. And you wouldn't make an int pointer and then always straight dereference it
@RevolutionaryUsername
@RevolutionaryUsername 11 ай бұрын
I’m a C++ programmer and it’s not a regular thing for me to need to define more than two raw pointers or references on the same line, so I always stick to int* and int&.
@tanmang42
@tanmang42 11 ай бұрын
Further, I think it's more visually consistent in principle of separating type and label- it's of type int*, not int so it reasons that the asterisk should be next to the type
@NightMind0
@NightMind0 11 ай бұрын
Why would you declare a reference?
@RevolutionaryUsername
@RevolutionaryUsername 11 ай бұрын
@@NightMind0 I’m not sure I understand the question. One obvious use case is accepting parameters by reference. Another is referencing a nested item to avoid the bother of having to keep accessing it every time. For example: if you have a struct called `items` that contains a vector and a string, you can do const auto& [vec, str] = items; You can now modify the nested items by modifying the reference variables ‘vec’ and ‘str’ // str = “hi”; // items.str is now == “hi” instead of having to call items.vec and items.str every time. A third reason is to selectively choose one of two expensive objects. Suppose you have two large strings and you want to apply operations on the larger string of the two only: const string& smaller = str1.size() > str2.size() ? str1 : str2; You have effectively chosen a particular string and did so without copying anything. There are many more uses but I don’t want to drag this comment out in case I misunderstood your question.
@ABaumstumpf
@ABaumstumpf 11 ай бұрын
@@NightMind0 Why would you not? As part of function-parameters, or cause you want to access some nested members, or to reference a element newly inserted into a container.
@NightMind0
@NightMind0 11 ай бұрын
@@ABaumstumpf OK, more specifically, why would you declare a reference from int? genuinely curious btw
@lamaspacos
@lamaspacos 8 ай бұрын
01:45 The one that makes more sense is the first: int *p 02:10 The clearest is the first one: int *p1 Thanks for the informative video.
@adruzgatsby
@adruzgatsby 9 ай бұрын
I'm seeing a lot of comments in favor of "int* p" and I use to be in that camp because I thought that p was a variable of type pointer to an integer. The videos in this channel are great, but this particular video doesn't fully explain the why "int *p" is actually the "correct" way to write a pointer and why it's written that way. I, like most of the folks here in the comment section came from a higher level language first while you have to understand that C was created in a time when many people were still writing assembly and C was considered a high level language! Modern languages today have sophisticated type systems while C's "trust me bro" type system with all it's casting magic (a feature, not a bug) really just specifies width. You are expecting more from the type system than you really should. When you declare a pointer, you should think of "int *p" as "if I dereference p, I'll get an int". The declaration offers a "hint" on how the variable should be invoked. The video showed one example of "int *p1, *p2;", but look at how arrays in C are written "int array[]", and not "int[] array" like they are written in Java. A language like Java that focuses on pass by reference, you really have that array is a variable of type int[]. In C, you are literally creating a contiguous chunk of memory on the stack, and the declaration offers a hint on how to access it. This is a much more powerful way of thinking about it, because if you end up with some crazy pointer declaration, it's very easy to reason about it because you know you have an address until you fully use the hint. Obviously there are crazier examples than a handle, but instead of thinking of "int **p" as a pointer to a pointer to an int, you can think of it as "my variable p will be an address until I fully follow through with what the declaration says and use **p".
@cccmmm1234
@cccmmm1234 11 ай бұрын
I've been using C for 40 years. I pretty much always use int *p. I also close to never declare more than one variable at a time.
@Flavio-ar
@Flavio-ar 11 ай бұрын
those of us who learned with k&r agree with you
@phitc4242
@phitc4242 11 ай бұрын
I have ~5 years of c experience. I am starting to sometimes declare multiple stuff on one line. depending on how lazy I am, since I know what I'm doing (in my freetime project; so who cares how I'm programming XD) I wonder if I ever get into the industry and how that evolves
@InfiniteQuest86
@InfiniteQuest86 11 ай бұрын
Yes, exactly. It looks so wrong the other way.
@cccmmm1234
@cccmmm1234 11 ай бұрын
@@phitc4242 It's a filthy habit. Ditch it before you're drawn to the wrong side.
@virno69420
@virno69420 11 ай бұрын
I'm young, started with C++ 12yrs ago. Always taught to use int* p. It makes way more sense, [type] [variable_name] right? So is pointer(*) the name of the variable, or apart of the type? (This is rhetorical btw) It obviously doesn't rly matter, but I know Stroustrup is on side [type]* [name]
@MrGeorge1896
@MrGeorge1896 11 ай бұрын
Just a small remark on the use of printf("%d ", sizeof(some_type)): In most environments the type of sizeof() is not int so the %d conversion specifier raises an error or at least a warning. The correct conversion specifier is %zu. z for the type of sizeof() which is defined as size_t and u as we are dealing with an unsigned value.
@clrkgmii
@clrkgmii 10 ай бұрын
Size uf
@ba-ba-ba-barspin5107
@ba-ba-ba-barspin5107 16 күн бұрын
we can learn from all this is that a silly change in the syntax with a same behaviour, makes developers get divided. Thanks for the video, it makes sense and i’ll never really spend more time on this, there are such more interesting topics !!
@marccygnus
@marccygnus 11 ай бұрын
Ive been doing embedded work for more than two decades. Some of it has been in safety critical systems. I've always used "int * p1" (space on either side of *). And I never declare multiple variables on one line. (C++ too.) I personally find the other two annoying to read.
@tubeincompetence
@tubeincompetence 11 ай бұрын
Haha.. I've just heard "Don't be a coward, commit to one or the other".. but not sure why :P I do prefer the asterisk at the type however.
@greatnate29
@greatnate29 11 ай бұрын
I also do this and it's just to remind me that the * is the actual data type, and the int is just what kind of pointer it is. Like an unsigned int is two keywords so should int *
@karimshariff7379
@karimshariff7379 Жыл бұрын
Thanks for this. As a beginner I would be tempted to use int* p1, p2 thinking that both p1 and p2 would be declared as pointers. Really appreciate this video. Oh, I have also done void main so I am watching that video next.
@PortfolioCourses
@PortfolioCourses Жыл бұрын
You're welcome Karim! :-) I'm glad you enjoyed it, and yes this is definitely a pitfall for new (and experienced) programmers.
@karimshariff7379
@karimshariff7379 Жыл бұрын
@@PortfolioCourses The other point of confusion I had was when in a function declaration we write: int func(int *p1). This is NOT to be read "The integer value that p1 points to" because what is being passed is an address. Therefore, in declarations do NOT read *p1 as "the integer value that p1 points to." In calls to the function we write: func(p1) to pass an address. I hope what I have said is correct.
@PortfolioCourses
@PortfolioCourses Жыл бұрын
I think the answer might be that it's OK to say "both". Because yes p1 stores a memory address. But p1 stores the memory address of an int. So saying "the integer value that p1 points to" in the context of discussing the function, the parameter, and arguments, isn't necessarily wrong... I think it would depend on the context in which the words were used. It's possible to say "the integer value that p1 points to" and have it be correct, it would depend on how it's used... e.g... "the int variable 'a' is set to 5, and we are passing &a to func, and so we are passing the int value that p1 points to (by pointer) to the function". We might use the term "by reference" as well. As a side note, you may find this video interesting: kzbin.info/www/bejne/iJbGqYSLiqqCpJY. And yes, when we call the function, we are passing an address (i.e. a pointer). :-)
@johnbode5528
@johnbode5528 10 ай бұрын
@@karimshariff7379 Honestly, the best way to think of '*p1' is as just another name for an 'int' object, both in the declaration and any expression that uses it. If you define a function as void doSomething( int *p1 ) { /* do something interesting with *p1 */ } void foo( void ) { int x; doSomething( &x ); } then you have this relationship: p1 == &x; // int * == int * *p1 == x; // int == int except that "*p1" isn't just the value of "x", it _designates the same object in memory_ as "x". The _expression_ "*p1" acts as a kinda-sorta alias for "x"; anywhere you use "*p1" in doSomething, you're actually using "x": *p1 = some_value; // equivalent to x = some_value printf( "%d ", *p1 ); // equivalent to printf( "%d ", x ); You probably don't spend any time thinking about how the subscript [] operator works, or how it's different between declarations and expressions; you just know that "int a[N]" declares an array and the expression "a[i]" refers to a specific object. Exact same thinking applies for the declaration "int *p1" and the expression "*p1".
@xTriplexS
@xTriplexS 11 ай бұрын
int* p: pointer to an int *p: p dereferenced p * q: p times q int&: reference to an int &p: address of p This is how I differentiate everything from each other
@guilhermecampos8313
@guilhermecampos8313 5 ай бұрын
Makes all the sense, the pointer * operator doesn't apply to the int keyword, but to the variable. This is why in "int *p1, p2;" only p1 is a pointer. Never thought about that. Man, you videos are very good, I'm clearing up a lot of doubts that I didn't even know I had.
@PortfolioCourses
@PortfolioCourses 5 ай бұрын
I’m really happy to hear these videos are clearing up doubts for you. :-)
@nicreven
@nicreven 10 ай бұрын
I've always hated "int *p"; I've noticed that people get confused by it, especially if you need to make a pointer to a pointer (an "int**" type thing) it's so much simpler and more understandable to think of p as a variable of the type "int*"
@mojeimja
@mojeimja 10 ай бұрын
look up pointer syntax in Pascal - it is much easier and understandable, including later dereferences.
@Biometrics
@Biometrics Ай бұрын
Thank you for this. My way of handling the confusion irrespective of whether there is a space in between or not is to say, *p1 is a pointer to an int address* . Otherwise if one says, p1 is a pointer to an int, that is where problems begin and the mind gets entangled in a never ending loop of confusion. So it gets easy to know that p1 is an address and that p1 can never be assigned a value because p1 can only be assigned an address only to another int address or only be assigned a dereferenced memory address of an int variable e.g. p1 = &num1 .
@Misteribel
@Misteribel 10 ай бұрын
p2 is an int-pointer, and p1 is a pointer that, when dereferenced, returns an int. They are the same thing in the end, but the way our brain reads code can influence how we write it.
@ProtossOP
@ProtossOP 11 ай бұрын
I’ve rationalised it like this when I was learning: int *p means that by dereferencing p you get int type back Int* p means variable p is of int* type, i.e. int pointer(which is not exactly the case but close enough)
@TrueThanny
@TrueThanny 11 ай бұрын
That's not how the language works. When declaring variables, you specify the data type, then a list of variable names. Each variable may or may not be a pointer to the data type in question.
@divVerent
@divVerent 11 ай бұрын
It actually is. Also: int func(float) says that func(some float) will be of int type. int (*func)(float) says the same but you have to dereference func first (which often is implicit - weird C). int a[3] similarly says that a[...] is of type int. That is the logic they used when designing C. We may not like it, but then the solution should be using a language that applies different notation, not working in the intersection of how it works and how we want it to work... And those languages already exist. Java, Go, Haskell, Rust, etc. all exist and do not do it the weird C way. We should just use those then rather than pretending C/C++ were something they aren't.
@samjohnson5044
@samjohnson5044 6 ай бұрын
Thank you for this! You give a very good reason for adopting a particular coding Style.
@kongolandwalker
@kongolandwalker 11 ай бұрын
My approach is to not declare multiple variables in one line. Exactly because of that int * p1, p2; inconsistency. One line creates different types - bad. My choice is int* p1; int* p2; It is clear type, clear distinction and intellisense is guaranteed not to mess up in-place hints when parsing that.
@gregorymorse8423
@gregorymorse8423 11 ай бұрын
That's why there are experts and there are noobs.
@soyitiel
@soyitiel 11 ай бұрын
I never go for either I've always preferred int * p since I don't consider the star to be part of the type only or the name only, but of both. It just looks cleaner to me.
@PLATONU
@PLATONU 9 ай бұрын
If you need a pointer to a pointer... do you use int ** ptr or int * * ptr ?
@soyitiel
@soyitiel 9 ай бұрын
@@PLATONU In cases like that I've used the non-seprated double stars since, just like a single star for a regular pointer, together the two stars form a type attribute
@markmidwest7092
@markmidwest7092 11 ай бұрын
I am not a C or C++ programmer, but I am interested in these two languages . . . For some reason, just watching you go through this very basic declaration of pointers, non pointers, dereferencing pointers, etc. suddenly helped things click for me. You didn't go through pointer arithmetic, obviously that was out of scope for your video but I've watched those, too and suddenly pointers make sense. Thank you for helping me put this all together.
@Scotty-vs4lf
@Scotty-vs4lf 11 ай бұрын
* (pointer + 1) is the same as array[1], whatever operation you do works in units of typeof( * pointer). so like pointer-- will move the pointer to what would be the previous element in an array, like doing int * p = &array[i-1] i had to do weird spacing cuz youtube thought i was trying to make my stuff bold
@Nunya58294
@Nunya58294 11 ай бұрын
Wait till your ass gets into bitwise operations and the binary system
@markmidwest7092
@markmidwest7092 11 ай бұрын
@@Nunya58294 I've been comfortable with bitwise operations since I was a kid but your comment did make me laugh. Thank you for that, I needed it today.
@ChaseAlberti
@ChaseAlberti 6 ай бұрын
Great explanation! In the embedded world I would argue that the "int * p3" decelerationis the most common. Although, in function declerations it would typically be "int const * p3"
@semibiotic
@semibiotic 11 ай бұрын
I always make variable names aligned on the same column for readability, whatever type is. Because of that I always align asterisk to type name, because it is part of variable type, not its name. I don't care what K&R were thinking doing such mess, I will do that my way for my own comfort and efficiency. If somebody would read my code and make such mistake, it would not be my fault. My code is not intended for noobs. I have no issues with the way how compiler works (I never declare multiple pointers in single declaration), or styles other coders use.
@enigmatico6209
@enigmatico6209 10 ай бұрын
You can avoid this problem by using a typedef to give int* an alias, or if you are programming for windows use one of the pointer types defined by Microsoft in windows.h. Then you can ignore the asterisk since it is implied by the type definition. But you also need to remember that you're dealing with a pointer.
@kensclark
@kensclark 11 ай бұрын
I tend to do "int* p" when declaring single variables, but "int *p, *p1" when declaring multiple.
@manyirons
@manyirons 11 ай бұрын
I hope the day this backfires on you is the day you stop doing this.
@merseyviking
@merseyviking 11 ай бұрын
I dislike multiple declarations, so I always make it explicit. It's not like our computers have such little memory that you need to keep your source code short :) I also do int* p; As others have pointed out, the * is part of the type, not the variable name. Sadly K&R disagree with me on that point.
@NoahtheEpicGuy
@NoahtheEpicGuy 11 ай бұрын
@@merseyviking Why do you dislike multiple declarations? I do multiple declarations not because of memory limitations (dunno why you'd ever think somebody would think that*) but rather for neatness and keeping the amount of unnecessary vertical space to a minimum by taking advantage of the miles of horizontal space. The problem of way too much vertical space usage is exacerbated in higher-level languages like Java, but I still try to be conservative with my C code so that somebody can gather most the information they need with as little movement as possible. Our computers have exponentially more memory, but us humans certainly do not. * I do know that people would think that, but your comment sounds a bit condescending to me, like you're assuming this random internet person is very sure to keep each source and header file under 4KiB, and that they should stop doing that along with declaring multiple variables on one line.
@shinobuoshino5066
@shinobuoshino5066 10 ай бұрын
@@NoahtheEpicGuy ah yes, the limited vertical space...
@Cyberfoxxy
@Cyberfoxxy 10 ай бұрын
Putting them line by line makes makes a clear list with 3 columns type/name/value. There's no need for the need horizontal gymnastics to interpret it. I usually allow single line declarations when the variables are closely related. E.g a matrix "float m00,m01,m10,m11" Or float x,y,z. But even then. You're better off with a struct.
@johnhanley2431
@johnhanley2431 9 ай бұрын
Good video. My suggestion is to expand your video to include typedefs. That will solve the confusion of type declarations. FYI: I worked on the AT&T Bell Labs team that wrote C and the Unix operating system. I was also involved in porting the C compiler to odd architectures including the 8086/80286 and Cray supercomputer. There is a lot of history behind some of the design choices we made for the language.
@pvjewel
@pvjewel 10 ай бұрын
non c programmer here. Always wondered that question. Thank you for clear explanation!
@finmat95
@finmat95 11 ай бұрын
The code must be readable and clear. int* ftw. P.s. even if you have to specify * for each variable in the same row, it doesn't mean it makes sense. Sometime even the standard and official syntax sucks.
@_sudipidus_
@_sudipidus_ 10 ай бұрын
To avoid confusion Right side is the value Left side is the type of Int *P means *P is the int which makes P as pointer Int* P means P is the integer pointer
@sergiogiacomosammartano7623
@sergiogiacomosammartano7623 11 ай бұрын
The fact is, when declaring a pointer, such as int *ptr; we are really saying to the compiler that we wanna use a reference variable called ptr to point to a chunk of memory that has to be the size of an int. Or, in other words, the expression "int *ptr" really means: if you will dereference this pointer ptr that I am declaring, you should get something of type int. Basically, declaring a reference by immediately showing that you can dereference it. Isn't that brilliant? :D Once this concept is clear, it will only become natural to put the star symbol (*) always close to the pointer's name, both when declaring it and when dereferencing it in expressions and statements. Same goes for the ampersand symbol &, used to represent addresses in C and even variables passed by reference in C++ (which really are copies of the arguments' addresses passed to the functions, by the way, hence the use of the "address of" operator & in such contexts). I always find awkward to see these symbols adjacent to a type descriptor, rather than to the actual variable name.
@filker0
@filker0 11 ай бұрын
Late to the game, but I am sn advocate of cuddling the asterisk with the type and not declaring multiple variables of any type on a single logical line. On many architectures, both 'int' and 'int*' are the same size. C is a free format language, so whitespace between tokens is arbitrary and when not required to delimit multi character tokens and identifiers, optional. I have been programing in C since 1981 and worked in compiler development for several years, so I am very set in my ways. I will continue to cuddle my asterisk with the type name because I believe it makes the code easier to read.
@HasanShokri
@HasanShokri 10 ай бұрын
I'm not a C programmer but I love your videos. This video made me subscribe to your channel. Keep up the good work!
@PortfolioCourses
@PortfolioCourses 10 ай бұрын
Welcome aboard! :-)
@JonitoFischer
@JonitoFischer 11 ай бұрын
What I like from int *p is that you can think that the variable pointed by p is of type int. Or when you use *p in your code, you're using an integer.
@minastaros
@minastaros 11 ай бұрын
Yes, but this "advantage" disappears as soon as you use struct pointers. Then you get e.g. car->doors even when _car_ is a pointer. And when you work with code that uses kind of an object oriented approach, you'll use struct pointers a lot...
@JonitoFischer
@JonitoFischer 11 ай бұрын
@@minastaros can't you use (*car).doors ?
@armedcannon
@armedcannon 11 ай бұрын
Section 6.7.6 in the c17 spec agrees, the * is part of the 'declarator'. Reading the * as part of the 'specifier' or type will fail in many non-trivial situations.
@minastaros
@minastaros 11 ай бұрын
@@JonitoFischer Technically, you could (and are free to do so), but you shouldn't. The arrow operator has a _semantic_ meaning (=member of an "object"), and is immediately recognized by any reader as such. I assume there was a strong reason in the past why they have created it, and not only to spare the two key strokes... ;-) Just saying, the position of the * is technically not important (and with *var you are even closer to the C habit in most code bases). But there are pointer operations that don't use an *, and with structs, "inheritance", polymorphism etc. it starts getting really powerful and interesting!
@armedcannon
@armedcannon 11 ай бұрын
"[W]hen an operand of the same form as the declarator appears in an expression, it designates [an] object with the (...) type indicated by the declaration specifiers."
@turdwarbler
@turdwarbler 9 ай бұрын
The reason why the most appropriate way to declare a pointer to int is int *p; is because the * is a unary operator, and unary operators bind more tightly to their operand which is why you put them together. There has always been a convention in C that you put a single space around binary operations and no space between a unary operator and its operand. Some other unary operators would be ++ -- & sizeof etc etc. Also you never imply precedence by spacing , hence never do A + B * C because visually when speed reading somebodys code you immediately assocciate the + first.
@Valerius123
@Valerius123 11 ай бұрын
I use p3 syntax because I use distinct syntax for declaring a pointer and de referencing them. This distinction makes the code look cleaner in my opinion. int * p3 = NULL; I also write my types from right to left because that's how they are best read and understood. For example: char const * const argv[] This is a constant pointer to a constant char. Where as this will often be written by most people as const char* const argv[] and they'd internalize it as "a const char pointer to a... const?" or something reading it from left to right.
@meowsqueak
@meowsqueak 11 ай бұрын
You’re right, and I agree, but sadly most haven’t seen the light yet, if ever.
@wertigon
@wertigon 11 ай бұрын
I rarely declare local pointers and if I do, I usually put them on a separate line for better readability, anyway. There is no reason not to. I do see your point, but any half-decent linter will catch that ambiguity. In my mind, pointers are a different type but a pointer can have a (sub) type. I usually tend to type void foo(int* bar, char* baz) as arguments, for instance. It really helps understanding both pointers and C in general, as the only two types a C program has is pointers and integers. And, on the extremely rare occasion you will need it, floating points - though 99% of the time fixed point just does a better job of decimals. At the end of the day though, I write code in whatever fashion I get paid to write.
@rretro2042
@rretro2042 11 ай бұрын
int* makes more sense because p is not actually an integer but rather a memory reference that points to an integer value
@aurinator
@aurinator 11 ай бұрын
Thanks for this quick video, I remember wondering this exact thing while learning.
@MarcoAurelio-sv2tk
@MarcoAurelio-sv2tk 5 ай бұрын
I think we shouldn't mix (in this case) pointer to an int and int. It might be confusing for the person that is reading the code. I personally like more the int *ptr notation, but in the end, the compiler doesn't care because it ignores the whitespaces
@rustycherkas8229
@rustycherkas8229 10 ай бұрын
While there are syntactic differences the "int *p;" style provides the foundation for "int *p[N];" being an array of pointers to int's; it is NOT a pointer to an array of int's... The "decorations" are to be interpreted primarily with the variable's name leaving the data's ultimate type being the final step of parsing. This same rule-of-thumb extends to everyone's favourite: function pointers. As to "stacking" several declarations together, consider "for( char *pLft = str, *pRgt = str + len; pLft < pRgt; pLft++, pRgt-- )" Two throwaway pointers whose scope is minimal.
@PortfolioCourses
@PortfolioCourses 10 ай бұрын
That’s a very good point. :-)
@OriginalJetForMe
@OriginalJetForMe 11 ай бұрын
I always thought it was a mistake that * binds to the right in a type declaration. If you typedef your int* then it makes more sense as a type. And multiple declarations on a line is just ugly.
@FredrikHistherRasch
@FredrikHistherRasch 10 ай бұрын
Worth pointing out: Guidelines and best practices in many programming languages is that each variable should be declared separately. Thus, keeping the asterisk next to the type remains true. The issue that introduces confusion is declaring multiple variables in one statement. If you always follow best practice and declare variables separately, the opinion that the asterisk is part of the type makes sense.
@shinobuoshino5066
@shinobuoshino5066 10 ай бұрын
I wonder why this guideline came to be... Wouldn't it just so happen that it's Cnile retardation like every other time?
@bikerinside_learn
@bikerinside_learn 10 ай бұрын
Always used star before name of pointer, recently in the latest Deitel C programming book, they suggested to use type* name_pointer, now with this video is very clear which notation to use.
@schifoso
@schifoso 11 ай бұрын
Go back 35 years and int* was rarely or never seen.
@yoops66
@yoops66 11 ай бұрын
Best ways to mitigate this risk: 1. One declaration per line 2. Use a typedef to define, say, intptr. IMHO, 'int* p' is more readable than 'int *p', in an eyeblink, especially on some occasions when people (rightly) justify definitions to vertically align variable names. In such cases, the * is much too far from the type, and the type is split into two parts, which is wrong.
@insu_na
@insu_na 10 ай бұрын
the very fact that `sizeof(int)` and `sizeof(int*)` have a different size (on a 64bit system) demonstrate to me that `int*` is a different type altogether, so grammatically it makes sense to me to keep it as such
@vvpChannel3112
@vvpChannel3112 9 ай бұрын
Amazing, I used to thought with int* all following variables are pointer type.. thanks sir for making this video
@MotorBorg
@MotorBorg 11 ай бұрын
I only recently started learning c, but I have experience with Pascal. I think Pascal style pointers are much more clear, declared like this P1: ^Integer; // P1 is pointer to integer dereferenced like this P1^ := 5; // P1 dereferenced assign 5 No ambiguity because dereferencing is postfix. But that's just my opinion.
@karlostj4683
@karlostj4683 11 ай бұрын
The compiler (gcc) only applies the '*' to the variable name immediately following it in the declaration. The solution to this is: Only declare one variable at a time - anything else is sloppy, which programmers should avoid like the plague.
@nottheevil
@nottheevil 9 ай бұрын
The moment when we actually use the third one in our projects. And I think it's actually the most logical one, since all parts of the specification are separated by spaces, then why not this one. And it still reads "integer pointer p1". It's actually totally in place when you do also "int & ref1" - then you have all your specifications more standardized. And yes, we have "int * & some_var"
@TechyAyush
@TechyAyush 10 ай бұрын
Excellent video! Really loved the way you present these concepts! Subscribed.
@PortfolioCourses
@PortfolioCourses 10 ай бұрын
You're welcome, I'm glad you enjoyed it! :-)
@davidgillies620
@davidgillies620 11 ай бұрын
This is a use case for typedefs, for example typedef int* intptr, although it can get messy if you try to be exhaustive;
@narfharder
@narfharder 11 ай бұрын
WIN32 API be like typedef unsigned int * * PPDWORD; or whatever - and I like it that way
@shinobuoshino5066
@shinobuoshino5066 10 ай бұрын
typedefs have no usecase and should've never existed
@narfharder
@narfharder 10 ай бұрын
For how well I know C, I don't code very much. So while I can't agree with your statement absolutely, I want to thank you for introducing me to the idea of typedefs being "suspicious" by default - it was never more than a vague thought in my head up to this point. A common-sense example I just found (and now agree with) from the Linux kernel style docs: "u8/u16/u32 are perfectly fine typedefs... New types which are identical to standard C99 types [are not forbidden]... In general, a pointer, or a struct that has elements that can reasonably be directly accessed should **never** be a typedef." Lesson: obfuscated type information is bad. Of course, a project's coding style should trump personal preference. You can imagine how disheartening it is to see someone pass a standard type (or worse, their own custom typedef) to a WIN32 API call. Argh, just use the type in the definition! Anyway, if you _insist_ on declaring your own types, typedef beats #define for sure (probably why they put it in C to begin with). Thanks for reading, friend.
@johnbode5528
@johnbode5528 10 ай бұрын
Typedefs hide information; if whoever's using that variable needs to be aware of its pointer-ness in order to use it properly (they need to dereference or use a subscript on it), then _don't_ hide that information behind a typedef. I once spent an afternoon chasing my tail because of a typedef that hid a pointer; I would rather have the eye-stabby version, at least it tells me what I need to know.
@davidgillies620
@davidgillies620 10 ай бұрын
@@johnbode5528 When was this? 1993? Any IDE or code editor today will let you drill down to the typedef in about three mouse clicks maximum. And then there's always RTFM.
@bertiesmith3021
@bertiesmith3021 10 ай бұрын
It’s important to understand what can go wrong because you have to work with other people’s code. But just avoid multiple declarations and it because a style issue I don’t care about. This is the same whether you are writing c or c++.
@UnlikelyToRemember
@UnlikelyToRemember 11 ай бұрын
I always use TAB; -- for example: int * p1; or char *p2; -- this way the variable names always line up so they are easier to read. Also, always one declaration per line.
@NoahtheEpicGuy
@NoahtheEpicGuy 11 ай бұрын
chaotic neutral unless your IDE automatically lines up adjacent tabs to match horizontal position. I used to code this way but realized it's much better using tabs to indent and spaces to align, because then it won't change no matter what tab size somebody uses. chaotic evil would be using spaces to indent and tabs to align. also, why does everybody say that only one declaration per line is better?
@RichardNeill01
@RichardNeill01 11 ай бұрын
The way to read this is "int *p" means "let *p be an int". It's tempting to think of it as "p is a variable of type int* " but firstly that doesn't always work (as per the video), and secondly, if you want to declare a variable as "the address of an int", then the logical way to define this would be "&int p" i.e. "p is of type address-of-int". In fact, neither "int*" nor "&int" are valid type definitions; but "int *p" works accidentally (sometimes), as a consequence of the whitespace not always being significant in C.
@bismajoyosumarto1237
@bismajoyosumarto1237 Жыл бұрын
The way I see it, writing int *ptr; signifies that, once you dereference the pointer, you get an int. With that in mind, I have no problem typing int *p1, p2, *p3, p4; since I would know very well that p1 and p3 are pointers (that point to an integer because their dereferenced type is int), while p2 and p4 are themselves integers.
@nothing-lo8lh
@nothing-lo8lh 11 ай бұрын
The reason I use int* ptr was bc the thing you said made sense to me, but when I tried to initalize "dereferenced ptr of type int" it required a memory address instead.
@bismajoyosumarto1237
@bismajoyosumarto1237 11 ай бұрын
@@nothing-lo8lh Hmm, fair point. I would get around that confusion by keeping the initialization separate from the type declaration, though that doesn't look good if I'm only declaring one variable
@__christopher__
@__christopher__ 11 ай бұрын
But then you start initializing it. And then you might think that int *p = 0; does the same as int *p; *p = 0. Which it doesn't.
@thorntontarr2894
@thorntontarr2894 10 ай бұрын
All of the discussion of pointers and the 'grammar' issues are clearly described. However, as a new coder, the term "dereferencing" is quite vague and potentially misunderstood. So instead of saying "dereferencing a pointer", I say "accessing the contents of the pointer", which explicitly describes the action of retrieving the value from the memory address pointed to by the pointer.
@codewizard58
@codewizard58 10 ай бұрын
The tokenization of C is straight forward. int*p1; Is also valid, the tokenizer looks for certain sequences that define identifiers, operators etc. such as a string of letters and numbers and _ starting with a letter or _. Any other character ends the token. white space is another way of ending a token. The grammar of C spells this out.
@tjdewolff5104
@tjdewolff5104 11 ай бұрын
Good video! However, for reasons of clarity I would split the declaration of the pointer variables over 2 lines: int *p1, *p2; This makes looking for the declaration and the properties of that declaration much easier to understand. I would even go so far as: int num = 5, *p1 = &num, *p2 = &num; This eliminates a few lines of code and "code that aint there" is code that needs no maintainance. And yes, the '*' should precede the variable name immediately and no space in between.
@MadMetalMacho
@MadMetalMacho 11 ай бұрын
Imo if you have int *p1 it's a bit weird, int* p1 makes way more sense. You don't write "cha rc" either, you do "char c". And the datatype of p1 is a pointer to an integer.
@tjdewolff5104
@tjdewolff5104 11 ай бұрын
@@MadMetalMacho I'm sorry, but I don't quite follow your statement. Care to elaborate?
@MadMetalMacho
@MadMetalMacho 11 ай бұрын
@@tjdewolff5104 it seems the stars somehow don't show up from my previous comment. I was talking about "int* ptr" vs "int *ptr"
@darckangenoir
@darckangenoir 11 ай бұрын
While it's good to know what the syntax truly is and does, I would say "prevent bugs by not declaring multiple variables in the same statement" as it also keeps it simple when reading the code, doing initialization, etc.
@SillyOrb
@SillyOrb 11 ай бұрын
I prefer the odd and seldomly used "int * p" because I can differentiate it from pointer dereferencing, which I write as "*p". Given that there is no correct notation and all of them have their pros and cons, you have to find a style that works for you and helps you do the things you do the most in the most efficient way. So, I also don't declare multiple variables in a single statement precisely due to this issue. I usually try to contain it to simple counters when setting up _for_ loops. It's not that much more work to have a single declaration per line. It usually pays off to type slightly more and then not having to debug the issues a misplaced * can cause, which can take minutes. Maybe that is different for you. I usually try to keep code debuggable and maintainable, instead of typing the least amount of characters, because I find that I usually only type code once (or a similarity low frequency), but then I have to step through the code many times whenever something changes (either new code or bugs).
@lellyparker
@lellyparker 11 ай бұрын
Declaring multiple variable in a single statement is less clear and readable than simply using a single statement to declare each variable. I personally would not recommend doing that.
@dronihack
@dronihack 9 ай бұрын
You want to keep your code cryptic and unmaintainable so you can keep your position
@oscargraveland
@oscargraveland 11 ай бұрын
What confused me for the longest was that the declaration of the pointer and the dereferencing of the pointer have the exact same syntax The variable holding the address of PeeOne: *p1 The value stored at address PeeOne : *p1
@GeorgeStaplin-tx6dc
@GeorgeStaplin-tx6dc 11 ай бұрын
I noticed the wrong type was used for a printf of the size_t. You should use the zu format-specifier.
@wettingfairy6764
@wettingfairy6764 11 ай бұрын
In the C language, both int* p and int *p have their advantages and disadvantages. Essentially, due to deficiencies in the type expression aspect of C language syntax design, neither of these two writing styles is perfect, and you can choose either one, as it is a matter of personal style. However, in the case of C++ language, int* p is evidently the better practice, more in line with the design philosophy of C++. This becomes particularly apparent when writing generic codes.
@NikolaNevenov86
@NikolaNevenov86 11 ай бұрын
Honestly the `int* p` makes more sense to me than the `int *p` , since the first reads as `int pointer of a name p`, while the second reads more like `integer of name star p`. Granted a star is a reserved symbol but still to me is clearer to see the first version than the second. I understand it's personal preference, but from what I see from the video, the second version is preferable mainly because of some weird compiler logic, that makes no sense to me. To me it makes sense that when you declare multiple variables on the same line with a single type at the start, the type applies for all variables(names) after it. Since (correct me if I'm wrong) but an `int` and an `int*` are not the same, especially in x64 systems where `pointers` are 8bytes and `integers` are 4bytes in memory.
@marshad82
@marshad82 11 ай бұрын
It makes no sense to you 'cause you do not understand it. Compiler's logic isn't weird, it's just parsing from right to left, and ignoring most whitespaces. Now read your own line: "To me it makes sense that..." . You can deduce from your own statement that _int*_ is not a type, instead _int_ is the correct type. Additionally "*" is a type called "pointer", that has a name, stated to the right of an asterisk (star), and storage type, to be found on the left side of an asterisk. With that in mind, and reading right to left, consider now this: _int ** ptr_ - "ptr" is a *pointer* to *pointer* to *int* . Now consider following declaration: _int arr [5]_ - it's not "integer named arr", that's an array of 5 elements of type *int* , but "arr" itself is a name of a *pointer* to *int* . Just like asterisk is declaring a pointer, so do square brackets, and just like asterisk used later in code is dereferencing a pointer (reaching to memory area, of a size of declared storage type, it is pointing toward) so are sq brackets: *arr = 4 is equal to arr[0] = 4, and arr[1] = 3 is equal to *(arr + 1) = 3. Difference is, that [] in declaration will allocate memory area on a stack for specified amount of elements, and that sizeof operator will be aware of it's size, as long as it is used within the same scope as array's declaration, as well as ability to use multidimensional arrays (you can however regain that ability by declaring a pointer to array: int (* myarr) [5]; myarr = some_pointer or some_address; myarr[1][3] = 69). Now this: _int * arr[5]_ - it's not "int pointer named arr", nor "integer named star arr", that's an array of 5 elements of type *pointer* to *int* , and "arr" is a name of a *pointer* to *pointer* to *int* . Names of ordinary variables are really just pointers, references, that auto-dereference themself: _int num;_ allocates area of stack equal to size of type int, _num = 7;_ auto-dereference to write binary representation of 7, in format representing type int, into pointed memory area. Personally I choose to use the third option: _int * ptr = NULL_ , as it makes sense when reading right to left - *ptr* is a *pointer* to *int* . Another example: _char * const ptr_ ( *ptr* is a *constant pointer* to *char* ), and by extension (which may trigger some): _char const * const ptr_ ( *ptr* is a *constant pointer* to *constant char* ) makes perfect sense, and AFAIK while parsing a "const" keyword, compiler will first look to the left of it (as in case of _char * const ptr_ ), and if it will find nothing, it will look to the right of it (as in case of _const int beast = 666_ ) All of this isn't that important, and you will have to adjust to whatever constraints your employer/environment will impose on you. Stuff like indenting, spaces after comas, semicolons, and around operators will impact readability way more than asterisk's placement. On a side note, if you ever struggle with understanding or writing a declaration, cdecl utility on linux can be helpful (online versions also available).
@NikolaNevenov86
@NikolaNevenov86 11 ай бұрын
@@marshad82 Well I see your point, but you are viewing it from the compiler's point of view and I don't think that's a better argument for one version or the other. Either way the compiler will compile the code. That being said the case with the array is syntax sugar. The `[]` brackets are just there to make life easy for the programmer and let the compiler handle the `*(arr+index)` statement. So if the compiler can do that, why shouldn't it be compiling a multiple declaration on a single line, where it treats the only type declaration as the type for all variable names? I mean the syntax is there, everything past the `,` is just varnames. As for the const...again personal preference but the way you wrote it still feels odd to me. Const states that the variable won't change after declaration, so `const int* varname` to me reads as `a constant integer pointer of name`, while `int const * varname` reads to me as `integer constant pointer of name`. Both are valid but the `const int* varname` to me reads more natural, than the Yoda speak. But I'm not a full time programmer but more of a hobbyist. That being said I'll accept your arguments as valid , if you can prove to me that `int *varname` and `int const * varname`, because is written the way "the compiler reads it", compiles faster than `int* varname` and `const int* varname`. Other than that it's just preferences.
@gnarfgnarf4004
@gnarfgnarf4004 11 ай бұрын
I prefer int *p, but the other version makes more sense when you realize that a reference to a pointer has to be coded as: int* &p;
@gnarfgnarf4004
@gnarfgnarf4004 10 ай бұрын
Very important observation.
@3NAS_N1
@3NAS_N1 2 жыл бұрын
Very informative video! Do you know of any reason why it was decidad that int* should not work for multiple variable declarations in the same line?
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
That’s a great question and I tried to figure out “why” before making this video, but there isn’t really a deep reason (that I could discover) beyond “they decided to make it work that way”. :-) That said I think this answer on stackoverflow provides some reasoning: stackoverflow.com/a/61861075. Basically variable declarations are split up into a “declaration specifiers” and “declarators”, where “static int” would be part of the declaration specifier portion but “a[10]” would be a declarator declaring an array with 10 elements. Now I don’t see why whether the variables being declared are pointers or not couldn’t be part of the “declaration specifier”. But I suspect they felt it belonged with the other declarators and so decided it would be specified there. The declarators seem focused on “structure” (pointer, array, function, etc.) so maybe that’s why they felt it fit there. But I’m just speculating, I’d love to know why. :-)
@3NAS_N1
@3NAS_N1 2 жыл бұрын
@@PortfolioCourses Oh I never thought about there being declaration specifiers and declarators, but it kind of makes sense. So writing int *p is basically a short form of int p[1] and in that sense it is quite obvious that it does not work for multiple declarations in the same line.
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
@@3NAS_N1 It's pretty similar the only thing is p[1] will be an array of 1 element and *p will be a pointer, and arrays and pointers can sometimes be used in place of the other but not always.
@3NAS_N1
@3NAS_N1 2 жыл бұрын
@@PortfolioCourses Oh yeah, you are right. I wrote my last response a little too quickly.
@HL1_EP1
@HL1_EP1 11 ай бұрын
3:32 You should rather use %zd which is the correct format specifier for the type size_t returned by the sizeof() function
@PortfolioCourses
@PortfolioCourses 11 ай бұрын
As long as we know the int is within the int range, %d will work. From C99 onwards we should use %zu for size_t, it will always be unsigned.
@filker0
@filker0 11 ай бұрын
Just a nit I must pick - 'sizeof' is an operator, not a function. This is a very important distinction because treating it as a function leads to serious bugs I have encountered.
@gregorymorse8423
@gregorymorse8423 11 ай бұрын
​@PortfolioCourses wrong int is 4 or 8 bytes on some platforms and pointer size is 4 or 8 bytes. One day you will learn about stack corruption...
@gregorymorse8423
@gregorymorse8423 11 ай бұрын
​@@filker0operators are functions. Learn your terminology. In C++ you can even overload them. sizeof is a compile time function and language keyword.
@stevebabiak6997
@stevebabiak6997 11 ай бұрын
Your pointer sizes being 8 indicates you are using a 64 bit system; compile and run that same code on a 32 bit system, and the size of your pointers will be 4, just like the size of the int type.
@PortfolioCourses
@PortfolioCourses 11 ай бұрын
That's true, that gets "addressed" in other videos (pun intended). :-)
@stevebabiak6997
@stevebabiak6997 11 ай бұрын
@@PortfolioCourses - what I was getting at is comparing “sizeof” values isn’t reliable for distinguishing a pointer from some other data type. This type of “exercise” could be misleading to those who don’t yet understand that principle.
@PortfolioCourses
@PortfolioCourses 11 ай бұрын
@@stevebabiak6997 Yes, I figured that. 🙂 I made no claim that this is a general method that can be used to distinguish pointers from other types, I just used it as a method to illustrate they are different types than might be expected in this instance and on my machine/compiler. I've been teaching C programming for 20 years and there's something about showing the sizeof() different types (especially pointers) which makes things "click" for beginner students (there is no typeof() in standard C).
@SamualN
@SamualN 10 ай бұрын
I've always hated `int foo, bar` and have always gone with the more explicit `int foo; int bar` and now I have a reason
@salomonchambi
@salomonchambi 2 жыл бұрын
Shortly after I started to learn C I saw this way of declaration int* p1; and it confused me because I've first learned int *p2; which is clearer to me, and got even more confused when I saw that on function declarations too, but eventually I figured it out that they are the same. Now, I don't recall to have seen int * p3; but now I'm aware of it thanks to your straightforward and clean explanation. Question, Is it a good practice to always (when possible) initialize your variables? Let's say NULL to pointers, 0 to int, etc.
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
Yes, it's a good practice. Generally it's nice if you initialize variables right when you declare them, but if you know you're going to initialize them soon after (e.g. after some other statements) that's going to be OK too.
@Andrew90046zero
@Andrew90046zero 11 ай бұрын
Funny thing is, my experience was the opposite. having the star next to the name also acted as an intuitional block to what I thought pointers did. It makes sence to think of the star as a part of the type itself, which makes sence, since "int*" is not the same as "int". The star modifies the type. But it's an unfortunate circumstance that when declaring multiple variables on one line, it has a very un-intuitional syntax. You assume all the variables on the line have the same type as is written at the start, but that isn't the case when considering pointers. Even though the star is essentially meant to define the type, just like how "int" does, but you don't write "int" multiple times on one line. So in my opinion, the way C handles the pointer-star on multi-var-single-line declarations is a bit jank in and of itself, and creates this unfortunate situation for developing a good intuition on pointers. Also, I personally don't declare multiple vars on one line anyway.
@benhetland576
@benhetland576 11 ай бұрын
@@Andrew90046zero As an extra complication this changes when you declare a typedef for the pointer type, for example like this: _typedef int * intp;_ _intp p1, p2;_ Now both _p1_ and _p2_ are pointers. Similar confusion may arise with function types, eg. _int* (*swap_ptr(int*p)),_ ptr to arrays of ptrs etc, so I often found it clearer and less errorprone to use typedef for more complicated types. The simplest declarations like just a pointer to sth I don't bother with, but for the "something" itself I prefer to have them as typedefs unless they are just primitive types (like an int). The reason I don't bother with the pointer (*) is because I rarely if ever declare more than one variable per line, and if I need a second declaration I start a new declaration on the next line complete with the type information AND initialize it too. Since modern C now allows declarations intermixed with statements the convenience of just declaring a bunch of variables on a single line at the top of the function is no longer relevant. Then it is better to declare each variable as late as possible and initialize it at the same time. That way the risk of using uninitialized vars (especially pointers!) is reduced or eliminated. You can also wait until the point where you have gathered enough information to initiate the variable to the correct/valid/desired value immediately.
@cleightthejw2202
@cleightthejw2202 Жыл бұрын
I definitely agree with the asterisk '*' being right next to the variable name instead of other places. It does seem to be easier to follow that over the other uses that could appear to be 'unclear' to ones reading it. That was a good view and was helpful on that point.
@PortfolioCourses
@PortfolioCourses Жыл бұрын
Agreed! :-)
@realdragon
@realdragon Жыл бұрын
Yeah my logic why I do that way is because variable is a pointer not the type
@simontillson482
@simontillson482 11 ай бұрын
Yep. Also, every textbook I’ve ever seen keeps the asterisk with the variable, never the type. This makes sense, since the asterisk modifies the variable. The type stays the same. Personally, looking at it the other way around, saying that the asterisk modifies the type from a type to a pointer-to-a-type just seems silly and confusing. It’s the behaviour of the variable that’s being modified - it’s become a pointer to a type instead of a value of a type. Therefore, the asterisk belongs with the variable that is being modified to become a pointer. (Just don’t mention typedef’d opaque pointers… shhh!)
@gregorymorse8423
@gregorymorse8423 11 ай бұрын
You are a noob. The variable name is not always next to the asterisk. Wait until you learn about constant or volatile pointers, my child.
@KyleHarrisonRedacted
@KyleHarrisonRedacted 10 ай бұрын
I’ve always put the star nestled up against the variable name. I saw the other style used and made a mental note of it. One day I’m hitting an issue and decide to see what happens if I put the star up against the type instead, wondering if there was a difference and to my shock it compiled and ran. When I moved the star back, it didn’t. I thought for a long time there that there must be some difference thanks to that but I wasn’t quite sure what. Then I went back and put the star where I normally would and decided to clean the build and recompile as fresh as possible.. and it worked. Some weird broken cache was the cause of my woes and I just didn’t see it. Now I’m paranoid and clean rebuild often.. I shouldn’t.. but once bitten twice shy lol
@Cyberfoxxy
@Cyberfoxxy 10 ай бұрын
This has been one of my pet peeves. I'm by no means a professional in cpp. But man the fact that it's a pointer is part of the type. Interesting that there's a caveat with multiple declarations. But honestly I think they should all be marked as the same type, wtf. Lastly I generally don't like multiple variables in one line and if I see them I get rid of them. I favour readability over being a smartass. I'll generally allow it if you need a lot of variables and the variables are somehow related. Like vectors x,y,z or matrices m00,m01,m10
@ghos7bear
@ghos7bear 10 ай бұрын
Thanks for comprehensive explanation. I've been reading C++ code over the years and this always confused me.
@nameless5724
@nameless5724 2 жыл бұрын
Very clear explanation.
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
I'm glad you enjoyed it! 😀
@feakhelek1
@feakhelek1 10 ай бұрын
At first it seems natural to put the * with the int since int* seems to indicate a pointer to an integer. After considering the behavior though it seems to me to make more sense to think of the * as a Unary Operator and putting it in front of the variable name reinforces that it is not part of the data type. I say that it is not part of the data type since at declaration the second variable declared is simply an int showing that the * has not been applied to it. A Unary Operator would only apply to the variable immediately following so in my mind it is easier to consider it an operator modifying the variable rather than the data type.
@minastaros
@minastaros 11 ай бұрын
1. Just don't declare two variables in one line. Never. Clean up or group variables otherwise, e.g. using structs, arrays etc. My variables have never names like p1 or p2, but much longer, expressive ones. With these, it gets messy quickly when several were declared in one line. You just lose the overview. 2. The compiler would bite you anyway if one of these variables (in the two-variables-in-a-line-example) was not a pointer by accident. 3. In C++, it is the official notation to put the * next to the type for a reason: because it clearly expresses the difference between a _type_ and a _dereference_ : int* is the type *var is the dereference 4. Therefore, for programmers like me who use both languages, it is more clean to use it consistently in both. So I chose the C++ notation. It just works better in the long term.
@slv8535
@slv8535 11 ай бұрын
BFD! "int", "*", and "p1" are three distinct tokens. It doesn't matter to the scanner where the whitespace is, or if there is no whitespace at all.
@semihaturkoglu
@semihaturkoglu 8 ай бұрын
you're the best instructor!!!
@PortfolioCourses
@PortfolioCourses 8 ай бұрын
Thank you for the kind feedback! :-)
@aspzx
@aspzx 11 ай бұрын
I understand why programmers have decided to place the star next to the variable name because of the risk of encountering this kind of bug but I can't for the life of me understand why the language designers chose to use this syntax. For example, Zig uses the syntax * to declare a pointer which is way clearer to me. Odin is similar except it uses ^ instead of *.
@RobbertdeGroot
@RobbertdeGroot 11 ай бұрын
Language designers, as far as I can recall, "Declare as how it will be used." Get the int from an int pointer. intVal = *intPtrVar; So declaration: int *intPtrVar;
@johnbode5528
@johnbode5528 10 ай бұрын
"Declaration mimics use." Given code like printf("%d ", *p); the _expression_ *p has type int, therefore the declaration is written int *p; Same with arrays; if the code is printf("%d ", a[i]); then the declaration of a is int a[N]; _not_ int[N] a;
@FSEAirboss
@FSEAirboss 10 ай бұрын
Oh the memories of writing C code on SSFD. We would write the code using whatever style was appropriate (white space, brace offsets, etc) and then promptly run it through a batch file process filter to remove all that so that the compilers would be 10 times faster not having to process all the white space used for readability. Oh, and all the fond memories of finding memory leaks. Those were the days! LOL
@friedrichmyers
@friedrichmyers 11 ай бұрын
Always used *p because it avoids errors and makes sense. One could argue that int pointer and int are different. Fine. But it makes the code less readable and error prone for the developer himself.
@ChiefExecutiveIntern5691
@ChiefExecutiveIntern5691 11 ай бұрын
My take as a C++ programmer is definitely that the * pointer annotation should be included with the type and not the name, just like the & reference symbol, const, or any other type modifiers. It's part of the variable's type, and not part of its name, as the pointer variable can be used and referenced without it. Any peculiarities or inconsistencies when declaring multiple variables on a single line is just a good reason not to declare multiple variables on a single line. And how often do you really need to initialize multiple variables of the same type with the same value?
@saeedgnu
@saeedgnu 11 ай бұрын
Probably one of the reasons Go uses var statements (as well as := type inference), like: var p1 *int It's much more logical and less confusing.
@aquilhall262
@aquilhall262 2 жыл бұрын
Thanks for the info! This is definitely a trap that would get a lot of people new to C like me. I will be vigilant!
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
You're welcome Aquil! 😀
@KANJICODER
@KANJICODER 11 ай бұрын
The first way is definitely proper in my opinion . But I do it the 2nd way because then I can do this : void some_function( int* *fake_pass_by_reference ){ ... } some_function( &( some_integer_pointer ) ); I do this on byte arrays that return bitmaps .
@DmitryKandiner
@DmitryKandiner 11 ай бұрын
Or you can just declare each variable at its own line. This way it's easier to change a type of a variable or comment it out completely.
@agdevoq
@agdevoq 10 ай бұрын
Although I don't like "int *p;", it also helps to rationalize the way pointer to functions are declared. "int (*pf)(int arg);" is a very ugly syntax, but basically you're just using parentheses to "tie" a star to the name of the function.
@tamaspolyak5564
@tamaspolyak5564 11 ай бұрын
Don't declare multiple variables in one line. Maybe except for some working variables in a small scope. If you declare each variable in its own line, you can use "pointer types" to make it clear what function they have. Try to initialize variables at declaration, make declarations as near as possible to where they are first used. If it's more than one person working on the code it will save hours searching for bugs.
@philkulibin2602
@philkulibin2602 11 ай бұрын
//Disagree . Proper way to do this typedef int * Pint; Pint p2, p3; // or auto p4= &num;
@gmfCoding
@gmfCoding 11 ай бұрын
Multiple declarations on a single line with typedef int* intp; intp p1, p2; gives 8, 8. Meaning both are pointers. Although its not a language feature I wish C had some cool tricks you could do like perhaps (int*) p1, p2. But I guess that could be confused with casting, perhaps, int* (p1, p2); hmm looks weird maybe I'm fine with just *p1, *p2
@hstrinzel
@hstrinzel 9 ай бұрын
Really helpful and clear! THANK YOU! :)
@andrewholden1501
@andrewholden1501 10 ай бұрын
I have a counterargument for all the people who say, "Just declare one variable per line, problem solved." That will work if you can guarantee you'll never be tasked with maintaining a crusty dinosaur that's older than your mother. Sadly, many of us can't guarantee that. Many companies have ancient turds still floating around, and someone has to keep them working. Heck, the very first program I ever handled professionally was a Fortran 4 program originally written in the 1950s, before the "if" statement was invented. The company was still using it in the late 90s, and probably still is today. Don't get me wrong, I fully support declaring one variable per statement. I just think it's important to be able to read the older style.
@PortfolioCourses
@PortfolioCourses 10 ай бұрын
Do I know you? :-) I know someone “IRL” named Andrew Holden.
@andrewholden1501
@andrewholden1501 10 ай бұрын
@@PortfolioCourses I don't think so. Would have been cool though.
@shinobuoshino5066
@shinobuoshino5066 10 ай бұрын
If I find any code using this shitty style I will just delete it without reading. Thank god I don't work in a soulless company.
@andrewholden1501
@andrewholden1501 10 ай бұрын
@@shinobuoshino5066 Excellent plan! Expect your boss to delete your job just as quickly!
@shinobuoshino5066
@shinobuoshino5066 10 ай бұрын
@@andrewholden1501 I'm my own boss, seethe.
@BryanChance
@BryanChance 11 ай бұрын
I learned the * next to the variable name. It makes sense to me because later, you deference the variable, not the type. Also, my reasoning is that I don't think of pointer as a type perse. Int is a type, the * is just a modifier to the variable. If you say pointer is a type, then int* and char* are pointers? They are, but more specifically, they are pointer to int and char types. Just my thoughts.. LOL if it doesn't make sense, disregard. My favorite language C. :-)
@justafriend5361
@justafriend5361 2 ай бұрын
But...if pointers are double in size, what's the matter of using them, if students have a hard time to learn and they can even cause big troubles in old PLC programs?
@paulathomas4944
@paulathomas4944 9 ай бұрын
Whitespace is ignored by the C compiler as anyone who's taken the time to read K&R knows only too well. So "int *p;" and "int* p;" both get fed into the compiler as "int*p;". I did many, many years of commercial C programming in the 80's and 90's. I never saw anybody use anything other than the "int *p" style of formatting. I take no joy in saying this but I feel your video is misleading and confusing for a beginner. It would have been much clearer if you simply explained that the compiler ignores whitespace.
@element4element4
@element4element4 3 ай бұрын
He essentially says that, but that is not the subtly addressed in the video.
@ramakrishna4092
@ramakrishna4092 2 жыл бұрын
Hi sir Is it possible to create a 2d or 2d array with single pointer dynamically if it is possible then why we need these many pointer like double pointer and triple pointer ( was there any disadvantages with using single pointer to all the array to create dynamically)... It's little bit confusing for beginners..can you pls help me Thank you sir
@PortfolioCourses
@PortfolioCourses 2 жыл бұрын
We can use a "single pointer" instead of a "double pointer" (i.e. a pointer to a pointer). But what we will have in that case is more like a 1D array of data, we would need to access the data differently than array[row][column]. We would need to access the data in the array like they do in the first example on this page: www.geeksforgeeks.org/dynamically-allocate-2d-array-c/. :-)
@johnbode5528
@johnbode5528 10 ай бұрын
This reply is likely too late to do any good, but ... Yes, you can create a 2D array with a single pointer, but it must be a pointer _to an array_ . Example: int (*arr)[C] = malloc( sizeof *arr * R ); allocates enough space for R instances (rows) of C-element arrays (columns) of 'int'. You index into the array like any 2D array: arr[i][j] = some_value; and when you're done, you only need a single call to "free": free( arr ); The difference between this and something like int **arr = malloc( sizeof *arr * R ); for ( size_t i = 0; i < R; i++ ) arr[i] = malloc( sizeof *arr[i] * C ); is that in the first method, all the rows are contiguous in memory, while in the second method they are not. Sometimes that matters. Also, in the second case, you must explicitly free each 'arr[i]' before freeing 'arr': for ( size_t i = 0; i < R; i++ ) free( arr[i] ); free( arr );
@strayling1
@strayling1 11 ай бұрын
This always made perfect sense to me. the base type is int, and anything else binds only to the variable. If that feels uncomfortable to anyone they can always use a typedef.
@Spoonbringer
@Spoonbringer 11 ай бұрын
Ugh please don't abuse typedef like that. To paraphrase Linus Torvalds, you generally shouldn't use typedef unless there is actually a reason for it. Like if you're using it for compatibility across platforms or to deliberately hide something. Typedefs are obfuscation by design.
@strayling1
@strayling1 11 ай бұрын
@@Spoonbringer I agree, and my suggestion was by no means a recommendation - I ported software across Unix platforms in the '90s. I've seen and done things ... that poor preprocessor ... but only because I had to. No, using a typedef to hide the way a language works just because you don't like the look of it is pretentious and asking for trouble.
Convert A For Loop To A While Loop | C Programming Tutorial
3:12
Portfolio Courses
Рет қаралды 9 М.
array vs &array Pointers Difference Explained | C Programming Tutorial
17:38
$1 vs $500,000 Plane Ticket!
12:20
MrBeast
Рет қаралды 122 МЛН
Непосредственно Каха: сумка
0:53
К-Media
Рет қаралды 12 МЛН
진짜✅ 아님 가짜❌???
0:21
승비니 Seungbini
Рет қаралды 10 МЛН
31 nooby C++ habits you need to ditch
16:18
mCoding
Рет қаралды 845 М.
Explaining Pointers Until I Go Insane
6:42
Mults
Рет қаралды 348 М.
why do header files even exist?
10:53
Low Level
Рет қаралды 444 М.
Pointers and dynamic memory - stack vs heap
17:26
mycodeschool
Рет қаралды 1,5 МЛН
Comparing C to machine language
10:02
Ben Eater
Рет қаралды 5 МЛН
Function Pointers | C Programming Tutorial
18:31
Portfolio Courses
Рет қаралды 70 М.
Master Pointers in C:  10X Your C Coding!
14:12
Dave's Garage
Рет қаралды 337 М.
WHY IS THE HEAP SO SLOW?
17:53
Core Dumped
Рет қаралды 287 М.
String In Char Array VS. Pointer To String Literal | C Programming Tutorial
9:58
you will never ask about pointers again after watching this video
8:03
$1 vs $500,000 Plane Ticket!
12:20
MrBeast
Рет қаралды 122 МЛН