Related
I have a question regarding a school lab assignment and I was hoping someone could clarify this a little for me. I'm not looking for an answer, just an approach. I've been unable to fully understand the books explanations.
Question: In a program, write a function that accepts three arguments: an array, the size of the array, and a number n.
Assume that the array contains integers. The function should display
all of the numbers in the array that are greater than the number n .
This is what I have right now:
/*
Programmer: Reilly Parker
Program Name: Lab14_LargerThanN.cpp
Date: 10/28/2016
Description: Displays values of a static array that are greater than a user inputted value.
Version: 1.0
*/
#include <iostream>
#include <iomanip>
#include <cmath>
using namespace std;
void arrayFunction(int[], int, int); // Prototype for arrayFunction. int[] = array, int = size, int = n
int main()
{
int n; // Initialize user inputted value "n"
cout << "Enter Value:" << endl;
cin >> n;
const int size = 20; // Constant array size of 20 integers.
int arrayNumbers[size] = {5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24}; // 20 assigned values for the array
arrayFunction(arrayNumbers, size, n); // Call function
return 0;
}
/* Description of code below:
The For statement scans each variable, if the array values are greater than the
variable "n" inputted by the user the output is only those values greater than "n."
*/
void arrayFunction(int arrayN[], int arrayS, int number) // Function Definiton
{
for (int i=0; i<arrayS; i++)
{
if (arrayN[i] > number)
{
cout << arrayN[i] << " ";
cout << endl;
}
}
}
For my whole answer I assume that this:
Question: In a program, write a function that accepts three arguments: an array, the size of the array, and a number n. Assume that the array contains integers. The function should display all of the numbers in the array that are greater than the number n .
is the whole assignment.
void arrayFunction(int[], int, int); is probably the only thing you could write. Note however that int[] is in fact int*.
As others pointed out don't bother with receiving input. Use something along this line: int numbers[] = {2,4,8,5,7,45,8,26,5,94,6,5,8};. It will create static array for you;
You have parameter int n but you never use it.
You are trying to send variable to the function arrayFunction but I can't see definition of this variable!
Use something called rubber duck debugging (google for it :) ). It will really help you.
If you have some more precise question, ask them.
As a side note: there are better ways of sending an array to the function, but your assignment forces you to use this old and not-so-good solution.
Would you use an if else statement? I've edited my original post with the updated code.
You have updated question, then I update my answer.
First and foremost of all: do indent your code properly!!!
If you do that, your code will be much cleaner, much more readable, and it will be much easier understandable not only for us, but primairly for you.
Next thing: do not omit braces even if they are not required in some context. Even experienced programmers only rarely omit them, so as a beginner you should never do so (as for example with your for loop).
Regarding if-else statement the short answer is: it depends.
Sometimes I would use if (note: in your case else is useless). But other times I would use ternary operator: condition ? value_if_true : value_if_false; or even a lambda expression.
In this case you should probably settle for an if, as it will be easier and more intuitive for you.
Aside from the C++ aspect, think about the steps you need to do to figure out if a number is greater than a certain value. Then do that for all the numbers in the array, and print out the number if it's greater than n. Since you have a 'for' loop, it looks like you already know how to do a loop and compare numbers in C++.
Also, it looks like in your arrayFunction you are trying to input values? You can't input a whole array's worth of values in a single statement like you appear to be trying (also, 'values' is not the name of any variable in arrayFunction, so that would not be recognized when you try to compile it).
Question #1: Is declaring a variable inside a loop a good practice or bad practice?
I've read the other threads about whether or not there is a performance issue (most said no), and that you should always declare variables as close to where they are going to be used. What I'm wondering is whether or not this should be avoided or if it's actually preferred.
Example:
for(int counter = 0; counter <= 10; counter++)
{
string someString = "testing";
cout << someString;
}
Question #2: Do most compilers realize that the variable has already been declared and just skip that portion, or does it actually create a spot for it in memory each time?
This is excellent practice.
By creating variables inside loops, you ensure their scope is restricted to inside the loop. It cannot be referenced nor called outside of the loop.
This way:
If the name of the variable is a bit "generic" (like "i"), there is no risk to mix it with another variable of same name somewhere later in your code (can also be mitigated using the -Wshadow warning instruction on GCC)
The compiler knows that the variable scope is limited to inside the loop, and therefore will issue a proper error message if the variable is by mistake referenced elsewhere.
Last but not least, some dedicated optimization can be performed more efficiently by the compiler (most importantly register allocation), since it knows that the variable cannot be used outside of the loop. For example, no need to store the result for later re-use.
In short, you are right to do it.
Note however that the variable is not supposed to retain its value between each loop. In such case, you may need to initialize it every time. You can also create a larger block, encompassing the loop, whose sole purpose is to declare variables which must retain their value from one loop to another. This typically includes the loop counter itself.
{
int i, retainValue;
for (i=0; i<N; i++)
{
int tmpValue;
/* tmpValue is uninitialized */
/* retainValue still has its previous value from previous loop */
/* Do some stuff here */
}
/* Here, retainValue is still valid; tmpValue no longer */
}
For question #2:
The variable is allocated once, when the function is called. In fact, from an allocation perspective, it is (nearly) the same as declaring the variable at the beginning of the function. The only difference is the scope: the variable cannot be used outside of the loop. It may even be possible that the variable is not allocated, just re-using some free slot (from other variable whose scope has ended).
With restricted and more precise scope come more accurate optimizations. But more importantly, it makes your code safer, with less states (i.e. variables) to worry about when reading other parts of the code.
This is true even outside of an if(){...} block. Typically, instead of :
int result;
(...)
result = f1();
if (result) then { (...) }
(...)
result = f2();
if (result) then { (...) }
it's safer to write :
(...)
{
int const result = f1();
if (result) then { (...) }
}
(...)
{
int const result = f2();
if (result) then { (...) }
}
The difference may seem minor, especially on such a small example.
But on a larger code base, it will help : now there is no risk to transport some result value from f1() to f2() block. Each result is strictly limited to its own scope, making its role more accurate. From a reviewer perspective, it's much nicer, since he has less long range state variables to worry about and track.
Even the compiler will help better : assuming that, in the future, after some erroneous change of code, result is not properly initialized with f2(). The second version will simply refuse to work, stating a clear error message at compile time (way better than run time). The first version will not spot anything, the result of f1() will simply be tested a second time, being confused for the result of f2().
Complementary information
The open-source tool CppCheck (a static analysis tool for C/C++ code) provides some excellent hints regarding optimal scope of variables.
In response to comment on allocation:
The above rule is true in C, but might not be for some C++ classes.
For standard types and structures, the size of variable is known at compilation time. There is no such thing as "construction" in C, so the space for the variable will simply be allocated into the stack (without any initialization), when the function is called. That's why there is a "zero" cost when declaring the variable inside a loop.
However, for C++ classes, there is this constructor thing which I know much less about. I guess allocation is probably not going to be the issue, since the compiler shall be clever enough to reuse the same space, but the initialization is likely to take place at each loop iteration.
Generally, it's a very good practice to keep it very close.
In some cases, there will be a consideration such as performance which justifies pulling the variable out of the loop.
In your example, the program creates and destroys the string each time. Some libraries use a small string optimization (SSO), so the dynamic allocation could be avoided in some cases.
Suppose you wanted to avoid those redundant creations/allocations, you would write it as:
for (int counter = 0; counter <= 10; counter++) {
// compiler can pull this out
const char testing[] = "testing";
cout << testing;
}
or you can pull the constant out:
const std::string testing = "testing";
for (int counter = 0; counter <= 10; counter++) {
cout << testing;
}
Do most compilers realize that the variable has already been declared and just skip that portion, or does it actually create a spot for it in memory each time?
It can reuse the space the variable consumes, and it can pull invariants out of your loop. In the case of the const char array (above) - that array could be pulled out. However, the constructor and destructor must be executed at each iteration in the case of an object (such as std::string). In the case of the std::string, that 'space' includes a pointer which contains the dynamic allocation representing the characters. So this:
for (int counter = 0; counter <= 10; counter++) {
string testing = "testing";
cout << testing;
}
would require redundant copying in each case, and dynamic allocation and free if the variable sits above the threshold for SSO character count (and SSO is implemented by your std library).
Doing this:
string testing;
for (int counter = 0; counter <= 10; counter++) {
testing = "testing";
cout << testing;
}
would still require a physical copy of the characters at each iteration, but the form could result in one dynamic allocation because you assign the string and the implementation should see there is no need to resize the string's backing allocation. Of course, you wouldn't do that in this example (because multiple superior alternatives have already been demonstrated), but you might consider it when the string or vector's content varies.
So what do you do with all those options (and more)? Keep it very close as a default -- until you understand the costs well and know when you should deviate.
I didn't post to answer JeremyRR's questions (as they have already been answered); instead, I posted merely to give a suggestion.
To JeremyRR, you could do this:
{
string someString = "testing";
for(int counter = 0; counter <= 10; counter++)
{
cout << someString;
}
// The variable is in scope.
}
// The variable is no longer in scope.
I don't know if you realize (I didn't when I first started programming), that brackets (as long they are in pairs) can be placed anywhere within the code, not just after "if", "for", "while", etc.
My code compiled in Microsoft Visual C++ 2010 Express, so I know it works; also, I have tried to to use the variable outside of the brackets that it was defined in and I received an error, so I know that the variable was "destroyed".
I don't know if it is bad practice to use this method, as a lot of unlabeled brackets could quickly make the code unreadable, but maybe some comments could clear things up.
For C++ it depends on what you are doing.
OK, it is stupid code but imagine
class myTimeEatingClass
{
public:
//constructor
myTimeEatingClass()
{
sleep(2000);
ms_usedTime+=2;
}
~myTimeEatingClass()
{
sleep(3000);
ms_usedTime+=3;
}
const unsigned int getTime() const
{
return ms_usedTime;
}
static unsigned int ms_usedTime;
};
myTimeEatingClass::ms_CreationTime=0;
myFunc()
{
for (int counter = 0; counter <= 10; counter++) {
myTimeEatingClass timeEater();
//do something
}
cout << "Creating class took " << timeEater.getTime() << "seconds at all" << endl;
}
myOtherFunc()
{
myTimeEatingClass timeEater();
for (int counter = 0; counter <= 10; counter++) {
//do something
}
cout << "Creating class took " << timeEater.getTime() << "seconds at all" << endl;
}
You will wait 55 seconds until you get the output of myFunc.
Just because each loop constructor and destructor together need 5 seconds to finish.
You will need 5 seconds until you get the output of myOtherFunc.
Of course, this is a crazy example.
But it illustrates that it might become a performance issue when each loop the same construction is done when the constructor and / or destructor needs some time.
Since your second question is more concrete, I'm going to address it first, and then take up your first question with the context given by the second. I wanted to give a more evidence-based answer than what's here already.
Question #2: Do most compilers realize that the variable has already
been declared and just skip that portion, or does it actually create a
spot for it in memory each time?
You can answer this question for yourself by stopping your compiler before the assembler is run and looking at the asm. (Use the -S flag if your compiler has a gcc-style interface, and -masm=intel if you want the syntax style I'm using here.)
In any case, with modern compilers (gcc 10.2, clang 11.0) for x86-64, they only reload the variable on each loop pass if you disable optimizations. Consider the following C++ program—for intuitive mapping to asm, I'm keeping things mostly C-style and using an integer instead of a string, although the same principles apply in the string case:
#include <iostream>
static constexpr std::size_t LEN = 10;
void fill_arr(int a[LEN])
{
/* *** */
for (std::size_t i = 0; i < LEN; ++i) {
const int t = 8;
a[i] = t;
}
/* *** */
}
int main(void)
{
int a[LEN];
fill_arr(a);
for (std::size_t i = 0; i < LEN; ++i) {
std::cout << a[i] << " ";
}
std::cout << "\n";
return 0;
}
We can compare this to a version with the following difference:
/* *** */
const int t = 8;
for (std::size_t i = 0; i < LEN; ++i) {
a[i] = t;
}
/* *** */
With optimization disabled, gcc 10.2 puts 8 on the stack on every pass of the loop for the declaration-in-loop version:
mov QWORD PTR -8[rbp], 0
.L3:
cmp QWORD PTR -8[rbp], 9
ja .L4
mov DWORD PTR -12[rbp], 8 ;✷
whereas it only does it once for the out-of-loop version:
mov DWORD PTR -12[rbp], 8 ;✷
mov QWORD PTR -8[rbp], 0
.L3:
cmp QWORD PTR -8[rbp], 9
ja .L4
Does this make a performance impact? I didn't see an appreciable difference in runtime between them with my CPU (Intel i7-7700K) until I pushed the number of iterations into the billions, and even then the average difference was less than 0.01s. It's only a single extra operation in the loop, after all. (For a string, the difference in in-loop operations is obviously a bit greater, but not dramatically so.)
What's more, the question is largely academic, because with an optimization level of -O1 or higher gcc outputs identical asm for both source files, as does clang. So, at least for simple cases like this, it's unlikely to make any performance impact either way. Of course, in a real-world program, you should always profile rather than make assumptions.
Question #1: Is declaring a variable inside a loop a good practice or
bad practice?
As with practically every question like this, it depends. If the declaration is inside a very tight loop and you're compiling without optimizations, say for debugging purposes, it's theoretically possible that moving it outside the loop would improve performance enough to be handy during your debugging efforts. If so, it might be sensible, at least while you're debugging. And although I don't think it's likely to make any difference in an optimized build, if you do observe one, you/your pair/your team can make a judgement call as to whether it's worth it.
At the same time, you have to consider not only how the compiler reads your code, but also how it comes off to humans, yourself included. I think you'll agree that a variable declared in the smallest scope possible is easier to keep track of. If it's outside the loop, it implies that it's needed outside the loop, which is confusing if that's not actually the case. In a big codebase, little confusions like this add up over time and become fatiguing after hours of work, and can lead to silly bugs. That can be much more costly than what you reap from a slight performance improvement, depending on the use case.
Once upon a time (pre C++98); the following would break:
{
for (int i=0; i<.; ++i) {std::string foo;}
for (int i=0; i<.; ++i) {std::string foo;}
}
with the warning that i was already declared (foo was fine as that's scoped within the {}). This is likely the WHY people would first argue it's bad. It stopped being true a long time ago though.
If you STILL have to support such an old compiler (some people are on Borland) then the answer is yes, a case could be made to put the i out the loop, because not doing so makes it makes it "harder" for people to put multiple loops in with the same variable, though honestly the compiler will still fail, which is all you want if there's going to be a problem.
If you no longer have to support such an old compiler, variables should be kept to the smallest scope you can get them so that you not only minimise the memory usage; but also make understanding the project easier. It's a bit like asking why don't you have all your variables global. Same argument applies, but the scopes just change a bit.
It's a very good practice, as all above answer provide very good theoretical aspect of the question let me give a glimpse of code, i was trying to solve DFS over GEEKSFORGEEKS, i encounter the optimization problem......
If you try to solve the code declaring the integer outside the loop will give you Optimization Error..
stack<int> st;
st.push(s);
cout<<s<<" ";
vis[s]=1;
int flag=0;
int top=0;
while(!st.empty()){
top = st.top();
for(int i=0;i<g[top].size();i++){
if(vis[g[top][i]] != 1){
st.push(g[top][i]);
cout<<g[top][i]<<" ";
vis[g[top][i]]=1;
flag=1;
break;
}
}
if(!flag){
st.pop();
}
}
Now put integers inside the loop this will give you correct answer...
stack<int> st;
st.push(s);
cout<<s<<" ";
vis[s]=1;
// int flag=0;
// int top=0;
while(!st.empty()){
int top = st.top();
int flag = 0;
for(int i=0;i<g[top].size();i++){
if(vis[g[top][i]] != 1){
st.push(g[top][i]);
cout<<g[top][i]<<" ";
vis[g[top][i]]=1;
flag=1;
break;
}
}
if(!flag){
st.pop();
}
}
this completely reflect what sir #justin was saying in 2nd comment....
try this here
https://practice.geeksforgeeks.org/problems/depth-first-traversal-for-a-graph/1. just give it a shot.... you will get it.Hope this help.
Chapter 4.8 Block Structure in K&R's The C Programming Language 2.Ed.:
An automatic variable declared and initialized in a
block is initialized each time the block is entered.
I might have missed seeing the relevant description in the book like:
An automatic variable declared and initialized in a
block is allocated only one time before the block is entered.
But a simple test can prove the assumption held:
#include <stdio.h>
int main(int argc, char *argv[]) {
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
int k;
printf("%p\n", &k);
}
}
return 0;
}
The two snippets below generate the same assembly.
// snippet 1
void test() {
int var;
while(1) var = 4;
}
// snippet 2
void test() {
while(1) int var = 4;
}
output:
test():
push rbp
mov rbp, rsp
.L2:
mov DWORD PTR [rbp-4], 4
jmp .L2
Link: https://godbolt.org/z/36hsM6Pen
So, until profiling opposes or computation extensive constructor is involved, keeping declation close to its usage should be the default approach.
How many pointers (*) are allowed in a single variable?
Let's consider the following example.
int a = 10;
int *p = &a;
Similarly we can have
int **q = &p;
int ***r = &q;
and so on.
For example,
int ****************zz;
The C standard specifies the lower limit:
5.2.4.1 Translation limits
276 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: [...]
279 — 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration
The upper limit is implementation specific.
Actually, C programs commonly make use of infinite pointer indirection. One or two static levels are common. Triple indirection is rare. But infinite is very common.
Infinite pointer indirection is achieved with the help of a struct, of course, not with a direct declarator, which would be impossible. And a struct is needed so that you can include other data in this structure at the different levels where this can terminate.
struct list { struct list *next; ... };
now you can have list->next->next->next->...->next. This is really just multiple pointer indirections: *(*(..(*(*(*list).next).next).next...).next).next. And the .next is basically a noop when it's the first member of the structure, so we can imagine this as ***..***ptr.
There is really no limit on this because the links can be traversed with a loop rather than a giant expression like this, and moreover, the structure can easily be made circular.
Thus, in other words, linked lists may be the ultimate example of adding another level of indirection to solve a problem, since you're doing it dynamically with every push operation. :)
Theoretically:
You can have as many levels of indirections as you want.
Practically:
Of course, nothing that consumes memory can be indefinite, there will be limitations due to resources available on the host environment. So practically there is a maximum limit to what an implementation can support and the implementation shall document it appropriately. So in all such artifacts, the standard does not specify the maximum limit, but it does specify the lower limits.
Here's the reference:
C99 Standard 5.2.4.1 Translation limits:
— 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration.
This specifies the lower limit that every implementation must support. Note that in a footenote the standard further says:
18) Implementations should avoid imposing fixed translation limits whenever possible.
As people have said, no limit "in theory". However, out of interest I ran this with g++ 4.1.2, and it worked with size up to 20,000. Compile was pretty slow though, so I didn't try higher. So I'd guess g++ doesn't impose any limit either. (Try setting size = 10 and looking in ptr.cpp if it's not immediately obvious.)
g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
#include <iostream>
int main()
{
const int size = 200;
std::cout << "#include <iostream>\n\n";
std::cout << "int main()\n{\n";
std::cout << " int i0 = " << size << ";";
for (int i = 1; i < size; ++i)
{
std::cout << " int ";
for (int j = 0; j < i; ++j) std::cout << "*";
std::cout << " i" << i << " = &i" << i-1 << ";\n";
}
std::cout << " std::cout << ";
for (int i = 1; i < size; ++i) std::cout << "*";
std::cout << "i" << size-1 << " << \"\\n\";\n";
std::cout << " return 0;\n}\n";
return 0;
}
Sounds fun to check.
Visual Studio 2010 (on Windows 7), you can have 1011 levels before getting this error:
fatal error C1026: parser stack overflow, program too complex
gcc (Ubuntu), 100k+ * without a crash ! I guess the hardware is the limit here.
(tested with just a variable declaration)
There is no limit, check example at Pointers :: C Interview Questions and Answers.
The answer depends on what you mean by "levels of pointers." If you mean "How many levels of indirection can you have in a single declaration?" the answer is "At least 12."
int i = 0;
int *ip01 = & i;
int **ip02 = & ip01;
int ***ip03 = & ip02;
int ****ip04 = & ip03;
int *****ip05 = & ip04;
int ******ip06 = & ip05;
int *******ip07 = & ip06;
int ********ip08 = & ip07;
int *********ip09 = & ip08;
int **********ip10 = & ip09;
int ***********ip11 = & ip10;
int ************ip12 = & ip11;
************ip12 = 1; /* i = 1 */
If you mean "How many levels of pointer can you use before the program gets hard to read," that's a matter of taste, but there is a limit. Having two levels of indirection (a pointer to a pointer to something) is common. Any more than that gets a bit harder to think about easily; don't do it unless the alternative would be worse.
If you mean "How many levels of pointer indirection can you have at runtime," there's no limit. This point is particularly important for circular lists, in which each node points to the next. Your program can follow the pointers forever.
It's actually even funnier with pointer to functions.
#include <cstdio>
typedef void (*FuncType)();
static void Print() { std::printf("%s", "Hello, World!\n"); }
int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}
As illustrated here this gives:
Hello, World!
Hello, World!
Hello, World!
And it does not involve any runtime overhead, so you can probably stack them as much as you want... until your compiler chokes on the file.
There is no limit. A pointer is a chunk of memory whose contents are an address.
As you said
int a = 10;
int *p = &a;
A pointer to a pointer is also a variable which contains an address of another pointer.
int **q = &p;
Here q is pointer to pointer holding the address of p which is already holding the address of a.
There is nothing particularly special about a pointer to a pointer. So there is no limit on chain of poniters which are holding the address of another pointer.
ie.
int **************************************************************************z;
is allowed.
Every C++ developer should have heard of the (in)famous Three star programmer.
And there really seems to be some magic "pointer barrier" that has to be camouflaged.
Quote from C2:
Three Star Programmer
A rating system for C-programmers. The more indirect your pointers are (i.e. the more "*" before your variables), the higher your reputation will be. No-star C-programmers are virtually non-existent, as virtually all non-trivial programs require use of pointers. Most are one-star programmers. In the old times (well, I'm young, so these look like old times to me at least), one would occasionally find a piece of code done by a three-star programmer and shiver with awe.
Some people even claimed they'd seen three-star code with function pointers involved, on more than one level of indirection. Sounded as real as UFOs to me.
Note that there are two possible questions here: how many levels of pointer indirection we can achieve in a C type, and how many levels of pointer indirection we can stuff into a single declarator.
The C standard allows a maximum to be imposed on the former (and gives a minimum value for that). But that can be circumvented via multiple typedef declarations:
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */
So ultimately, this is an implementation issue connected to the idea of how big/complex can a C program be made before it is rejected, which is very compiler specific.
I'd like to point out that producing a type with an arbitrary number of *'s is something that can happen with template metaprogramming. I forget what I was doing exactly, but it was suggested that I could produce new distinct types that have some kind of meta maneuvering between them by using recursive T* types.
Template Metaprogramming is a slow descent into madness, so it is not necessary to make excuses when generating a type with several thousand level of indirection. It's just a handy way to map peano integers, for example, onto template expansion as a functional language.
Rule 17.5 of the 2004 MISRA C standard prohibits more than 2 levels of pointer indirection.
There isn't such a thing like real limit but limit exists. All pointers are variables that are usually storing in stack not heap. Stack is usually small (it is possible to change its size during some linking). So lets say you have 4MB stack, what is quite normal size. And lets say we have pointer which is 4 bytes size (pointer sizes are not the same depending on architecture, target and compiler settings).
In this case 4 MB / 4 b = 1024 so possible maximum number would be 1048576, but we shouldn't ignore the fact that some other stuff is in stack.
However some compilers may have maximum number of pointer chain, but the limit is stack size. So if you increase stack size during linking with infinity and have machine with infinity memory which runs OS which handles that memory so you will have unlimited pointer chain.
If you use int *ptr = new int; and put your pointer into heap, that is not so usual way limit would be heap size, not stack.
EDIT Just realize that infinity / 2 = infinity. If machine has more memory so the pointer size increases. So if memory is infinity and size of pointer is infinity, so it is bad news... :)
It depends on the place where you store pointers. If they are in stack you have quite low limit. If you store it in heap, you limit is much much much higher.
Look at this program:
#include <iostream>
const int CBlockSize = 1048576;
int main()
{
int number = 0;
int** ptr = new int*[CBlockSize];
ptr[0] = &number;
for (int i = 1; i < CBlockSize; ++i)
ptr[i] = reinterpret_cast<int *> (&ptr[i - 1]);
for (int i = CBlockSize-1; i >= 0; --i)
std::cout << i << " " << (int)ptr[i] << "->" << *ptr[i] << std::endl;
return 0;
}
It creates 1M pointers and at the shows what point to what it is easy to notice what the chain goes to the first variable number.
BTW. It uses 92K of RAM so just imagine how deep you can go.
Someone told me: "declaring variables close to their use have value". He corrected me:
void student_score(size_t student_list_size) {
// int exam;
// int average;
// int digit;
// int counter_digits;
for (size_t i = 0; i < student_list_size; i++) {
int exam;
int average;
int digit;
int counter_digits;
I think it's bad, because here variables initialized every loop. What's true?
I encourage to declare them in as local a scope as possible, and as close to the first use as possible. This makes it easier for the reader to find the declaration and see what type the variable is and what it was initialized to. And of course, compiler will optimize it.
Both methods would be optimised to the same thing by the compiler. But for readability and ease of future maintenance, declaring the variables within the loop might be preferred by some.
I think it's bad, because here variables initialized every loop. What's true?
The code given the variables are not initialised at all.
So it is just a matter of personal taste.
It depends. C and C++ work differently in that regard. In C, variables MUST be declared at the start of its scope (forget that, it depends on your compiler although it holds true in pre-C99 compilers, as pointed out in the comments - thanks guys!), while in C++ you can declare them anywhere.
Now, it depends. Let's suppose the following two pieces of code:
int i = 0;
while (i < 5) {
i++;
}
while (i < 5) {
int i = 0;
i++;
}
In this case, the first piece of code is what's gonna work, because in the second case you declare the variable at each loop. But, let's suppose the following...
int i = 0;
while (i < 5) {
std::String str = "The number is now " + std::to_string(i);
cout << str << endl;
i++;
}
In short, declare the variables where it makes most sense to you and your code. Unless you're microoptimizing, like most things, it all depends on context.
This seems like a discussion with many personal opinions, so I'll add mine: I am a C programmer and like the C rules of having to declare your variables at the begining of a function (or block). For one thing, it tells me the stack lay-out so if I create another bug (I do "occassionaly") and overwrite something, I can determine the cause from just the stack lay-out. Then, when having to go through C++ code, I always have to search where the variable is declared. I rather look at the function beginning and see them all neatly declared.
I do ocassionally want to write for (int i=0;... and know the variable goes out of scope following the for loop (I hope it goes out of scope, as it is declared before the block begins).
Then there is an example in another answer:
while (i < 5) {
int i = 0;
i++;
}
and I hope it doesn't work because if it works it means there must be a variable i declared before this loop and so you have a clash of variables and scopes which can be horrible to debug (the loop will never terminate because the wrong i is incremented). I mean, I hope all variables must have been declared before their use.
I believe you must have a discipline in declaring your variables. The discipline can vary per person, just as long as it is easy to find where a variable is declared and what its scope is.
First of all that is not valid C code unless you are using -std=c99.
Furthermore, as long as you aren't creating dangling pointers in the loop, there is no problem with it.
The advantage you gain from doing it this way is that these variables are in a tight knit scope.
You need to know some knowledge of what local variable is ?
A variable declared inside a function is known as local variable. Local variables are also called automatic variables.
Scope: The area where a variable can be accessed is known as scope of variable.
Scope of local variable:
Local variable can be used only in the function in which it is declared.
Lifetime:
The time period for which a variable exists in the memory is known as lifetime of variable.
Lifetime of local variable:
Lifetime of local variables starts when control enters the function in which it is declared and it is destroyed when control exists from the function or block.
void student_score(size_t student_list_size) {
// int exam;
// int average;
// int digit;
// int counter_digits;
/* The above variable declared are local to the function student_score and can't be used
in other blocks. In your case its the for loop. */
for (size_t i = 0; i < student_list_size; i++) {
int exam;
int average;
int digit;
int counter_digits;
...
/* The above declared variable are local to the for loop and not to the function.*/
Consider this example:
#include<stdio.h>
void fun();
int main()
{
fun();
return 0;
}
void fun()
{
int i,temp=100,avg=200;
for (i=0;i<2;i++)
{
int temp,avg;
temp = 10 + 20;
avg = temp / 2;
printf("inside for loop: %d %d",temp,avg);
printf("\n");
}
printf("outside for loop: %d %d\n",temp,avg);
}
Output:
inside for loop: 30 15
inside for loop: 30 15
outside for loop: 100 200
If you are declaring the variable in loops the then declare the variable as static (In case if the value of the variable to be saved/used for further iteration).
Even compiler spend lot of time to initialize the variable in loops.
My suggestion is to declare at the beginning of the function. its a good programming practice.
I think, i made my point.
How many pointers (*) are allowed in a single variable?
Let's consider the following example.
int a = 10;
int *p = &a;
Similarly we can have
int **q = &p;
int ***r = &q;
and so on.
For example,
int ****************zz;
The C standard specifies the lower limit:
5.2.4.1 Translation limits
276 The implementation shall be able to translate and execute at least one program that contains at least one instance of every one of the following limits: [...]
279 — 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration
The upper limit is implementation specific.
Actually, C programs commonly make use of infinite pointer indirection. One or two static levels are common. Triple indirection is rare. But infinite is very common.
Infinite pointer indirection is achieved with the help of a struct, of course, not with a direct declarator, which would be impossible. And a struct is needed so that you can include other data in this structure at the different levels where this can terminate.
struct list { struct list *next; ... };
now you can have list->next->next->next->...->next. This is really just multiple pointer indirections: *(*(..(*(*(*list).next).next).next...).next).next. And the .next is basically a noop when it's the first member of the structure, so we can imagine this as ***..***ptr.
There is really no limit on this because the links can be traversed with a loop rather than a giant expression like this, and moreover, the structure can easily be made circular.
Thus, in other words, linked lists may be the ultimate example of adding another level of indirection to solve a problem, since you're doing it dynamically with every push operation. :)
Theoretically:
You can have as many levels of indirections as you want.
Practically:
Of course, nothing that consumes memory can be indefinite, there will be limitations due to resources available on the host environment. So practically there is a maximum limit to what an implementation can support and the implementation shall document it appropriately. So in all such artifacts, the standard does not specify the maximum limit, but it does specify the lower limits.
Here's the reference:
C99 Standard 5.2.4.1 Translation limits:
— 12 pointer, array, and function declarators (in any combinations) modifying an
arithmetic, structure, union, or void type in a declaration.
This specifies the lower limit that every implementation must support. Note that in a footenote the standard further says:
18) Implementations should avoid imposing fixed translation limits whenever possible.
As people have said, no limit "in theory". However, out of interest I ran this with g++ 4.1.2, and it worked with size up to 20,000. Compile was pretty slow though, so I didn't try higher. So I'd guess g++ doesn't impose any limit either. (Try setting size = 10 and looking in ptr.cpp if it's not immediately obvious.)
g++ create.cpp -o create ; ./create > ptr.cpp ; g++ ptr.cpp -o ptr ; ./ptr
create.cpp
#include <iostream>
int main()
{
const int size = 200;
std::cout << "#include <iostream>\n\n";
std::cout << "int main()\n{\n";
std::cout << " int i0 = " << size << ";";
for (int i = 1; i < size; ++i)
{
std::cout << " int ";
for (int j = 0; j < i; ++j) std::cout << "*";
std::cout << " i" << i << " = &i" << i-1 << ";\n";
}
std::cout << " std::cout << ";
for (int i = 1; i < size; ++i) std::cout << "*";
std::cout << "i" << size-1 << " << \"\\n\";\n";
std::cout << " return 0;\n}\n";
return 0;
}
Sounds fun to check.
Visual Studio 2010 (on Windows 7), you can have 1011 levels before getting this error:
fatal error C1026: parser stack overflow, program too complex
gcc (Ubuntu), 100k+ * without a crash ! I guess the hardware is the limit here.
(tested with just a variable declaration)
There is no limit, check example at Pointers :: C Interview Questions and Answers.
The answer depends on what you mean by "levels of pointers." If you mean "How many levels of indirection can you have in a single declaration?" the answer is "At least 12."
int i = 0;
int *ip01 = & i;
int **ip02 = & ip01;
int ***ip03 = & ip02;
int ****ip04 = & ip03;
int *****ip05 = & ip04;
int ******ip06 = & ip05;
int *******ip07 = & ip06;
int ********ip08 = & ip07;
int *********ip09 = & ip08;
int **********ip10 = & ip09;
int ***********ip11 = & ip10;
int ************ip12 = & ip11;
************ip12 = 1; /* i = 1 */
If you mean "How many levels of pointer can you use before the program gets hard to read," that's a matter of taste, but there is a limit. Having two levels of indirection (a pointer to a pointer to something) is common. Any more than that gets a bit harder to think about easily; don't do it unless the alternative would be worse.
If you mean "How many levels of pointer indirection can you have at runtime," there's no limit. This point is particularly important for circular lists, in which each node points to the next. Your program can follow the pointers forever.
It's actually even funnier with pointer to functions.
#include <cstdio>
typedef void (*FuncType)();
static void Print() { std::printf("%s", "Hello, World!\n"); }
int main() {
FuncType const ft = &Print;
ft();
(*ft)();
(**ft)();
/* ... */
}
As illustrated here this gives:
Hello, World!
Hello, World!
Hello, World!
And it does not involve any runtime overhead, so you can probably stack them as much as you want... until your compiler chokes on the file.
There is no limit. A pointer is a chunk of memory whose contents are an address.
As you said
int a = 10;
int *p = &a;
A pointer to a pointer is also a variable which contains an address of another pointer.
int **q = &p;
Here q is pointer to pointer holding the address of p which is already holding the address of a.
There is nothing particularly special about a pointer to a pointer. So there is no limit on chain of poniters which are holding the address of another pointer.
ie.
int **************************************************************************z;
is allowed.
Every C++ developer should have heard of the (in)famous Three star programmer.
And there really seems to be some magic "pointer barrier" that has to be camouflaged.
Quote from C2:
Three Star Programmer
A rating system for C-programmers. The more indirect your pointers are (i.e. the more "*" before your variables), the higher your reputation will be. No-star C-programmers are virtually non-existent, as virtually all non-trivial programs require use of pointers. Most are one-star programmers. In the old times (well, I'm young, so these look like old times to me at least), one would occasionally find a piece of code done by a three-star programmer and shiver with awe.
Some people even claimed they'd seen three-star code with function pointers involved, on more than one level of indirection. Sounded as real as UFOs to me.
Note that there are two possible questions here: how many levels of pointer indirection we can achieve in a C type, and how many levels of pointer indirection we can stuff into a single declarator.
The C standard allows a maximum to be imposed on the former (and gives a minimum value for that). But that can be circumvented via multiple typedef declarations:
typedef int *type0;
typedef type0 *type1;
typedef type1 *type2; /* etc */
So ultimately, this is an implementation issue connected to the idea of how big/complex can a C program be made before it is rejected, which is very compiler specific.
I'd like to point out that producing a type with an arbitrary number of *'s is something that can happen with template metaprogramming. I forget what I was doing exactly, but it was suggested that I could produce new distinct types that have some kind of meta maneuvering between them by using recursive T* types.
Template Metaprogramming is a slow descent into madness, so it is not necessary to make excuses when generating a type with several thousand level of indirection. It's just a handy way to map peano integers, for example, onto template expansion as a functional language.
Rule 17.5 of the 2004 MISRA C standard prohibits more than 2 levels of pointer indirection.
There isn't such a thing like real limit but limit exists. All pointers are variables that are usually storing in stack not heap. Stack is usually small (it is possible to change its size during some linking). So lets say you have 4MB stack, what is quite normal size. And lets say we have pointer which is 4 bytes size (pointer sizes are not the same depending on architecture, target and compiler settings).
In this case 4 MB / 4 b = 1024 so possible maximum number would be 1048576, but we shouldn't ignore the fact that some other stuff is in stack.
However some compilers may have maximum number of pointer chain, but the limit is stack size. So if you increase stack size during linking with infinity and have machine with infinity memory which runs OS which handles that memory so you will have unlimited pointer chain.
If you use int *ptr = new int; and put your pointer into heap, that is not so usual way limit would be heap size, not stack.
EDIT Just realize that infinity / 2 = infinity. If machine has more memory so the pointer size increases. So if memory is infinity and size of pointer is infinity, so it is bad news... :)
It depends on the place where you store pointers. If they are in stack you have quite low limit. If you store it in heap, you limit is much much much higher.
Look at this program:
#include <iostream>
const int CBlockSize = 1048576;
int main()
{
int number = 0;
int** ptr = new int*[CBlockSize];
ptr[0] = &number;
for (int i = 1; i < CBlockSize; ++i)
ptr[i] = reinterpret_cast<int *> (&ptr[i - 1]);
for (int i = CBlockSize-1; i >= 0; --i)
std::cout << i << " " << (int)ptr[i] << "->" << *ptr[i] << std::endl;
return 0;
}
It creates 1M pointers and at the shows what point to what it is easy to notice what the chain goes to the first variable number.
BTW. It uses 92K of RAM so just imagine how deep you can go.