Why is a variable declared outside an if block not accessible? [duplicate] - go

This question already has answers here:
Why does golang compiler think the variable is declared but not used?
(1 answer)
Declared but not used
(1 answer)
How to avoid annoying error "declared and not used"
(9 answers)
Closed 8 months ago.
I use a pattern where a variable is declared outside of an if-block and the block determines the value to assign to it. The compiler does not like the following code and reports: "result declared but not used". It looks proper to me... Please explain what I am misunderstanding.
Thank you for your help,
Mike
func blah() {
var result error = nil // "result declared but not used"
if 1 == 1 {
result = fmt.Errorf("ouch")
}
}

Assigning a value into a variable is not using that variable.
This is also an error (here compiler never read the variable so it's not used) .
var result string // "result declared but not used"
result = "sheikh"
"Every declared variable have to be used" means compiler have to read the value of that variable and use it to perform at least one operation (arithmetic Operation or assignment Operation or Unary Operation or Relational Operation)
This is not an error,
var result int
result+=1
This is not an error,
var result int
result=1
if result == 1 {
}
If you want to avoid this error simply do this,
var result int
result=1
_=result

Related

Getting cgo runtime error "cgo argument has Go pointer to Go pointer"

I'm using cgo to write a service using a C library that we're using. I'm new to Go.
I'm having a runtime error on the following line:
status = int(C.VeProtect(C.VeObj(fpeProtect), &argsProtect))
The trace I get is:
panic serving [::1]:55146: runtime error: cgo argument has Go pointer to Go pointer
goroutine 20 [running]:
net/http.(*conn).serve.func1()
/usr/local/go/src/net/http/server.go:1801 +0x13a
panic({0xc21cc0, 0xc000093700})
/usr/local/go/src/runtime/panic.go:1047 +0x262
voltagems/voltagefuncs.protectAndAccess.func1(0x0, 0xc0000b2960)
/media/sf_winhome/git/voltagego/voltagefuncs/voltagefuncs.go:71 +0x90
First, I can't even tell from this which argument it's talking about, although I would guess it's the first one.
The type of "fpeProtect is "C.VeFPE", and the type of that is "*_Ctype_struct_VeFPE_st". That struct type has a handful of "_Ctype_int" properties, and several "*_Ctype_char" properties. I didn't directly set any properties of that object, it was passed to a couple of C methods that would have populated some of the fields.
If I understand it correctly, the implication of that error message is that one or more properties of that struct is a pointer to a Go object, not a C object. I don't see how that could be possible, but I also can't tell exactly what property it's complaining about.
Update:
#JimB made me realize that the issue is likely with the second parameter, not the first. I think that's correct, but the assignments associated with that were already complex.
These are the assignments in question:
argsProtect.plaintext = (*C.uchar)(&([]byte)(data)[0])
argsProtect.plaintextSize = C.uint(len(data))
const BufSize int = 256
var textBuffer []byte = make([]byte, BufSize)
argsProtect.ciphertext = (*C.uchar)(&textBuffer[0])
The "data" variable is type "string". The type of both "plaintext" and "ciphertext" is "*_Ctype_uchar".
How can I convert those "plaintext" and "ciphertext" assignments to fulfill the requirement of producing a "*C.uchar", but converting the GoPointer to a CPointer?
Update:
I think I may have fixed the ciphertext assignment, but I think the plaintext assignment needs to be fixed also. Here is the changed block:
argsProtect.plaintext = (*C.uchar)(&([]byte)(data)[0])
argsProtect.plaintextSize = C.uint(len(data))
const BufSize int = 256
textBuffer := C.malloc(C.ulong(C.sizeof_char * BufSize))
argsProtect.ciphertext = (*C.uchar)(textBuffer)
argsProtect.ciphertextBufferSize = C.uint(BufSize)
status = int(C.VeProtect(C.VeObj(fpeProtect), &argsProtect))
This still fails on the last line with "cgo argument has Go pointer to Go pointer".

Error: Function 'vsrnggaussian' at (1) has no IMPLICIT type [duplicate]

This question already has answers here:
Why do I have to specify implicitly for a double precision return value of a function in Fortran?
(2 answers)
Function has no implicit type
(4 answers)
Closed 1 year ago.
I'm new to Fortran (gcc version 10.2.0) and try to use the subroutine 'vsrnggaussian' to generate normally distributed random numbers but always get following error:
"Error: Function 'vsrnggaussian' at (1) has no IMPLICIT type"
I don't get it since 'vsrnggaussian' is no variable that needs to be defined.
What's wrong with my code?
program test_normaldistr_random_number
!
USE iso_fortran_env, dp=>real64
!
IMPLICIT NONE
!
INTEGER :: VSL_RNG_METHOD_GAUSSIAN_BOXMULLER
REAL(DP) :: n=1._dp, a=10._dp, sigma=2._dp, stream=1._dp
REAL :: r = 1, status
!
status = vsrnggaussian(VSL_RNG_METHOD_GAUSSIAN_BOXMULLER,
&stream, n, r, a, sigma)
!
print *, status
!
end program

C++11 redeclaration in range-based for loop

This code compiles in Visual Studio 2015 update 3 (and here: visual C++ compiler online , and does not in other compilers I have tried online (GCC and CLANG), giving a redeclaration error
vector<int> v = {1,2,3};
for (auto i : v) {
printf("%d ", i);
int i = 99;
printf("%d ", i);
}
output: 1 99 2 99 3 99
VS C++ online compiler (version: 19.10.24903.0) warns about this:
warning C4456: declaration of 'i' hides previous local declaration
Is there some space in the C++11 spec to allow for both implementations to be valid?
Seems to me that VS2015 is creating a scope for the "auto i", and an inner scope for the loop body.
Adding an extra scope, as a colleague suggested, compiles fine in the other compilers I have tested (not that I wanted this, it's just for curiosity):
vector<int> v = {1,2,3};
for (auto i : v) {{
printf("%d ", i);
int i = 99;
printf("%d ", i);
}}
thanks
EDIT:
Ok, after reading this other question Redeclaration of variable in range-based for loops and the answer from "Angew", I believe that VS is actually correct.
I am reading here: cpp reference
Given this grammar description:
for ( range_declaration : range_expression ) loop_statement
and what this is equivalent to:
{
auto && __range = range_expression ;
for (auto __begin = begin_expr, __end = end_expr;
__begin != __end; ++__begin) {
range_declaration = *__begin;
loop_statement
}
}
I understand that loop_statement is actually my entire block including the brackets, so the redefinition is indeed in an inner block, hence valid.
EDIT 2:
My last edit, for future reference, reading the traditional for loop grammar is a similar situation (cpp for loop) as the range-based:
for ( init-statement condition(optional); iteration_expression(optional) ) statement
"The above syntax produces code equivalent to:"
{
init_statement
while ( condition ) {
statement
iteration_expression ;
}
}
So looking back, I could also interpret/parse statement as my inner block, including the braces, for which I would at least expect a consistent behavior in which ever compiler I am. But ALL compilers will bail out with a redeclaration error for the traditional for-loop.
N4606 (C++17 draft) 3.3.3 basic.scope.block, section 4 says
Names declared in the
init-statement
, the
for-range-declaration
, and in the
condition
of
if
,
while
,
for
, and
switch
statements are local to the
if
,
while
,
for
, or
switch
statement (including the controlled statement),
and shall not be redeclared in a subsequent condition of that statement nor in the outermost block (or, for
the
if
statement, any of the outermost blocks) of the controlled statement; see 6.4
shortened:
Names declared in the ... for-range-declaration ... are local to the ... for ... and shall not be redeclared in a subsequent condition of that statement nor in the outermost block
I read this as saying it should not be allowed.
Is there some space in the C++11 spec to allow for both implementations to be valid?
With one exception the only answer to that is no.
The exception is for global variables, where you can use the scoping operator :: to reach them. Otherwise, if you shadow the name of a variable in an outer scope, you no longer have access to it.

Order of evaluation when using an increment operator to set the value of statement parameters [duplicate]

This question already has answers here:
Incrementor logic
(7 answers)
How do the post increment (i++) and pre increment (++i) operators work in Java?
(14 answers)
Closed 6 years ago.
Is this the proper syntax in order to set the parameters of a previously generated preparedstatement? Which occurs first, the addition of 1 to the variable i, or the usage of the variable in setting the parameter?
int i=1;
for (TagInfo tag : scannedTags){
//Pull the tag from the dbo.Tags table that matches the SiteID and TagOffSet values of the current tag in the alarm_tags list
//Set parameters for the prepared statement
dbStmtTag.setInt(i++, tag.getSiteID());
dbStmtTag.setInt(i++, tag.getTagOffset());
}
If the order of operations is that the value is incremented first, I would assume I can just add 1 AFTER setting the parameter. I'm merely asking for the sake of brevity in my code.
[To test the behaviour of i++ for myself] I'd have to write an entire test application that talks to a test database, which I would need to create.
Nonsense. All you would need to do is ...
public static void main(String[] args) {
try {
int i = 1;
System.out.printf("i is %d%n", i);
System.out.printf("i++ returned %d%n", i++);
System.out.printf("i is now %d%n", i);
} catch (Exception e) {
e.printStackTrace(System.err);
}
}
... which produces ...
i is 1
i++ returned 1
i is now 2

Why does the debugger have to jump "back and forth" before it sets my tuple value?

I've actually fixed this problem already (while documenting it for this post), but I still want to know is why it is happening, so that I can understand what I did and hopefully avoid wasting time with it in the future.
In a Swift project, I have a function that parses out a string that I know will be presented in a specific format and uses it to fill in some instance variables.
There is a helper function that is passed the string, a starting index, and a divider character and spits out a tuple made up of the next string and the index from which to continue. Just in case a poorly formatted string gets passed in, I define a return type of (String, Int)? and return nil if the divider character isn't found.
The helper function looks, in relevant part, like this:
func nextChunk(stringArray: Array<Character>, startIndex: Int, divider: Character) -> (String, Int)?
{
[...]
var returnValue: (String, Int)? = (returnString, i)
return returnValue
}
So far, so good. I set a breakpoint, and just before the function returns, I see that all is as it should be:
(lldb) po returnValue
(0 = "21三體綜合症", 1 = 7)
{
0 = "21三體綜合症"
1 = 7
}
That's what I expected to see: the correct string value, and the correct index.
However, when I go back to the init() function that called the helper in the first place, and put a breakpoint immediately after the call:
var returnedValue = self.nextChunk(stringArray, startIndex: stringArrayIndex, divider: " ")
I get a completely different value for returnedValue than I had for returnValue:
(lldb) po returnedValue
(0 = "I", 1 = 48)
{
0 = "I"
1 = 48
}
Now here's the really weird part. After I get the return value, I want to test to see if it's nil, and if it's not, I want to use the values I fetched to set a couple of instance variables:
if(returnedValue == nil)
{
return
}
else
{
self.traditionalCharacter = returnedValue!.0
stringArrayIndex = returnedValue!.1
}
If I comment out both of the lines in the "else" brackets:
else
{
// self.traditionalCharacter = returnedValue!.0
// stringArrayIndex = returnedValue!.1
}
then my original breakpoint gives the expected value for the returned tuple:
(lldb) po returnedValue
(0 = "21三體綜合症", 1 = 7)
{
0 = "21三體綜合症"
1 = 7
}
Again: the breakpoint is set before this if/else statement, so I'm taking the value before any of this code has had the chance to execute.
After banging my head against this for a few hours, I realize that...there isn't actually a problem. If I press the "step over" button in the debugger, the execution pointer jumps back from the if() line to the call to nextChunk. Pressing it again sends it forward to "if" again, and sets the values properly.
This extra double-jump only happens if the assignment code is active, consistently and reproducibly. As I know, since I reproduced it for hours trying to figure out what was wrong before even trying stepping forward and noticing that it "fixed itself."
So my question is: why? Is this a bug in the debugger, or am I using breakpoints wrong? It happens just the same whether I put the breakpoint between the function call and the if() or on the if() line. Can someone explain why the debugger is jumping back and forth and when the value I need is actually getting set?

Resources