Compiler showing warning during compilation of the following code [duplicate] - c++

This question already has answers here:
warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char (*)’
(3 answers)
Closed 5 years ago.
#include<stdio.h>
int main()
{
char str[6][50] ; // a 2d character array
int i ;
for(i = 0 ; i < 6 ; i++)
{
scanf("%s",(str+i)) ; // in here the warning was shown
}
return 0 ;
}`
During Output :-
scanf() is showing warning on compilation - warning: format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[50]’ [-Wformat=]

Remember that arrays naturally decays to pointers to their first element? That means str by itself is treated as a pointer. With str + i you are doing pointer arithmetic, the result of which is another pointer (to the i:th element in this case). The type of that pointer is a pointer to an array, char (*)[50], it's not the array itself.
What you need to do is to dereference the pointer: *(str + i). Or as it's the same, str[i].

It seems like you are trying to access each element of str in turn. To do this use scanf("%s",str[i]); (as per usr's comment).

Related

C++ cannot assign to return value because function 'operator []' returns a const value [duplicate]

This question already has answers here:
C++ std::set update is tedious: I can't change an element in place
(7 answers)
std::set iterator automatically const [duplicate]
(2 answers)
Closed 1 year ago.
Hi every one I'm new to C++, and practicing it by leetcode.
Today when I was trying lc127, this error confused me. This error comes from one ranged for statement, where variable first is of the type unordered_set. And if I removed the reference mark&, then it works all right.
The most minimal reproducible example is like:
unordered_set<string> first{ beginWord }, last{ endWord };
int i = 0, j = 'a';
for (auto& word : first) {
word[i] = j;//error here
}
And the error shows:
Line 17: Char 33: error: cannot assign to return value because function 'operator[]' returns a const value
word[i] = j;
~~~~~~~ ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/9/../../../../include/c++/9/bits/basic_string.h:1045:7: note: function 'operator[]' which returns const-qualified type 'std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>::const_reference' (aka 'const char &') declared here
const_reference
^~~~~~~~~~~~~~~
My question is that why the former version is wrong? To my understanding, if I want to change the value in a ranged for statement, then I should use a & to ensure that I changed the value?
Full code link:Full code is here
Thank you in advance!

Passing a 2D Array to function in C++ [duplicate]

This question already has answers here:
Passing a 2D array to a C++ function
(18 answers)
How do I use arrays in C++?
(5 answers)
What is array to pointer decay?
(11 answers)
Closed 1 year ago.
I tried passing a 2D array to a function in C++ and I didn`t understand something:
//My array declaration:
int array[5][5]={{....}}; //I declared and filled the array with values
//My different function tries:
void passArr(int **array) //ERROR
void passArr(int *array[5]) //ERROR
void passArr(int *(*array)) //ERROR
void passArr(int (*(*array))) //ERROR
void passArr(int (*array)[5]) //WORKS
All errors were: [Error] cannot convert 'int (*)[5]' to 'int**' for argument '1' to 'void passArr(int**)'
Why do the errors show up and most importantly what is the difference between int *array[5] and int (*array)[5] when passing as an argument?
If int (*array)[5] worked, then why didn´t int *(*array) or int (*(*array))) also work?
In C and C++, a 2D array is an Array-of-Arrays. The first element of a 2D array is the first 1D array it contains. The conversion is specified in C++ Standard - Array-to-pointer Conversion [conv.array]
When you declared a plain-old 2D array as:
int array[5][5]
You have an array of int[5] arrays. As with any array, it is converted to a pointer to its first element on access. The first element being an array of int[5], so the resulting type is:
int (*)[5]
A pointer-to-array-of int[5]. So for your 2D array named array, that is:
int (*array)[5]
They're just different things. Reading from right to left might be helpful.
int array[5][5] -> array of array of int, could decay to pointer to array of int
int (*array)[5] -> pointer to array of int, could be converted from the above
int **array -> pointer to pointer to int
int *(*array) -> same as above
int (*(*array)) -> same as above
int *array[5] -> array of pointer to int
Also, in the "C++" language, it is strongly advisable to use one of the very-many "container classes" for this purpose. Or perhaps a class of your own devising.
"A simple pointer" has no way to convey that it is pointing to "a 2D array," nor what its dimensions are. The extent of its job-description is that it knows how to point to "a bunch of bytes, or nothing."
But if instead you provided your caller with a reference to a class, your caller could now "ask the class" for what it needed, "and the class would magically know." Just hand the class (X,Y) and you either get the right answer or a runtime exception is thrown. Every single time ... and by the way, efficiently.
This is a much more-robust way to write code, and it really is the reason why the C++ language was invented.
Versions 1,3, and 4 are all the same. Version 2 is also the same as 1,3, and 4, because when passing an array to a function the array decays to a pointer.
Version 2 can also be written
void passArr(int* array[5])
Which probably shows the association of the asterisk with the type more clearly: it is an array of five int-pointers. With the array decaying to a pointer, it becomes
void passArr(int** array)
All of them mean that the entry of the array are addresses, pointing to another array:
[ * | * | * | * | * ]
| | | | +-> [,,,,]
| | | +-> [,,,,]
And so on.
What you have is an array when each entry is an array of 5 ints, not a pointer to one (arrays bear a lot of resemblance with pointers, but they aren't pointers!)
Your matrix looks like this:
[ [1,2,3,4,5], [6,,,,], [,,,,], [,,,,], [,,,,] ]
So, array is a pointer to an int[5], not a pointer to pointer to int. And that is what the parentheses do in version 5: int (*array)[5]. This binds the asterisk closer to array.

Why does C++ always display a Hexadecimal memory address and not just an integer?

I wanted to know why printing the address of a variable in c gives the output as something like 823759733
while, doing the same in c++ shows 0x7ff6474009c??
Is this the work of 'cout', that formats the address as a hex? or is the variable memory address cloaked to show some arbitrary address to encapsulate it??
I know that everything is going on inside virtual memory in C++, is this the same for C?
example -
int a=10;
int* ptr=&a;
printf("%d", ptr);
it should print an integer.
the same code written in c++
and
cout<<ptr
it shows a hex(I want to know why?)
I guess you are printing in C something like this:
void* p;
...
printf("%d", p);
The %d specifier prints as an integer, output as base-10.
And I guess in C++ you're doing something like:
void* p;
...
std::cout << p;
Here, because of C++ strong typing, cout knows p is a pointer, and not an integer. Pointers are output in base 16 by default.
That's the problem
printf("%d", ptr);
The result can be completely wrong. On my system a int has 4 bytes and a pointer has 8 bytes. When I try to print a pointer as decimal (%d) it causes undefined behavior. In my example I see the undefined behavior as overflow. You should use %p to print pointers
printf("%p", ptr);
Your compiler should show you a warning like
warning: format '%d' expects argument of type 'int', but argument 2 has type 'int *' [-Wformat=]
An example of
#include <stdio.h>
int main() {
int a;
int* ptr = &a;
printf("%d", ptr);
}
Compile output:
prog.c: In function 'main':
prog.c:5:14: warning: format '%d' expects argument of type 'int', but argument 2 has type 'int *' [-Wformat=]
5 | printf("%d", ptr);
| ~^ ~~~
| | |
| int int *
| %ls
Runtime output:
-204940372
The role of format specifiers for printf in C is taken by different overloads for operator<< in C++. In the C code you didn't show you explicitly asked to print the decimal representation, when you call std::cout::operator<< the appropriate overload is chosen. Printing memory adresses as hex is the common convention. If you like you can print them as decimals in C and in C++.

Store pointer to 2d array [duplicate]

This question already has answers here:
How do I declare a 2d array in C++ using new?
(29 answers)
Closed 8 years ago.
So I have a private member in the class Map:
char **_map;
I then try to initialize the pointer array to a two dimensional char array like this:
std::vector<std::string> contents = StringUtils::split(_mapInfo.getContents(), ' ');
const int x = StringUtils::toInt(contents.at(0));
const int y = StringUtils::toInt(contents.at(1));
_map = new char[x][y];
Basically the contents vector contains two strings, which I then convert into integers. I then try to initialize the map array but I receive this error:
Error 1 error C2540: non-constant expression as array bound
And this:
Error 2 error C2440: '=' : cannot convert from 'char (*)[1]' to 'char **'
And finally this:
3 IntelliSense: expression must have a constant value
The last error references the variable y
Can anyone explain what is happening and how I can fix it?
The initialization of 2d array is as following;
char **_map;
_map = new char*[rowsize];
for(int row = 0; row < rowsize; ++row)
{
_map[row] = new char[columnsize]
}

Why is this code on array of structures working?

This code on array of structures is working but according to my understanding it shoudn't.
Code:
#include<stdio.h>
#include<string.h>
int main()
{
struct virus {
char signature[25];
char status[20];
int size;
} v[2] = {
"Yankee Doodle", "Deadly", 1813,
"Dark Avenger", "Killer", 1795
};
for(int i=0;i<=1;i++) {
printf("%s %s\n", &v[i].signature, &v[i].status);
}
return 0;
}
According to me, when we try to access the members of a structure using the address of an instance of the structure, we must use the -> operator rather than the . operator. I know that we do it only in case a pointer,but as far as I know, array is functionally equivalent to a pointer. Please help me where I am going wrong with my concepts. And pardon my silly question, because I am just a beginner.
It should not according to Operator Precedence. [] has higher precedence than ., and . has higher precedence than &. So &v[i].signature is equivalent to & ( (v[i]).signature). So first the ith item is taken from v, then it's signature member is accessed, which is a character array, and then & is applied which gives the address of the character array.
It works in VS, but this is not standard behavior.
It doesn't really work. You probably expected &v[i].signature to be (&v[i]).signature (which should have been (&v[i])->signature), but it's actually &(v[i].signature), of type char (*)[25]. If the program still produces the expected output, then that's purely by chance.
GCC would have told you this even without -Wall:
$ gcc -c a.c
a.c: In function ‘main’:
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char (*)[25]’ [-Wformat=]
printf("%s %s\n",&v[i].signature,&v[i].status);
^
a.c:18:9: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[20]’ [-Wformat=]
It's working because:
&v[i].signature == &v[i] == v->signature
(&v).signature == v->signature
You have taken the address using & and dereferenced using [].